# PatentRef API changes What changed in what the API answers or expects, newest first. The version is info.version of https://patentref.io/openapi.json; https://patentref.io/llms.txt and https://patentref.io/llms-full.txt name the same version. Rule: 1.MINOR.PATCH. The 1 is the /api/v1/ grammar and stays while it does. MINOR goes up when a request gets back or must send something different: a field or header added, dropped or shown under a new condition, a parameter newly required, a new endpoint, a generated sentence reworded. PATCH goes up when only the documents change. Keep the version with anything you cache from the documents, and read them again when it changes. ## 1.21.0 (2026-11-02) - New endpoint: GET /api/v1/structure/brief//?max_tokens= (the trailing slash is optional), a brief of one granted patent in a fixed order: its identity and dates, its status record with its basis, each independent claim with its elements, one line for each dependent claim, and the claim term keys, cut to fit max_tokens (300 to 32000, default 2000) by a stated proxy, ceil(utf8_bytes / 3), and never over it; truncated and omitted say what the budget left out. Every quote carries its start and end in the claim text and is checked before the answer leaves; no language model, nothing stored. It needs X-Api-Key and counts toward the monthly allowance like every data path. 400 ERR_Q (also for a max_tokens outside 300 to 32000), 404 NOT_FOUND, 500 ERR_ES, 501 ERR_NOT_IMPLEMENTED, 503 ERR_ES when the status records cannot be read. https://patentref.io/docs/structure.html#brief - The record page https://patentref.io/p/ shows the patent's claims below its record, with an anchor on each claim (c) and on each element (c-e--), the same for the same data; a link to an anchor the page no longer has opens its claim with a note. https://patentref.io/docs/structure.html#links - New endpoint: GET /api/v1/structure/counts// (the trailing slash is optional), the claim counts of one granted patent in the spirit of the USPTO Patent Claims Research Dataset (the USPTO's claims data for grants of 1976 to 2014), for any grant the long-text file in service holds. Per patent: the claims, the independent and dependent claims, the claims whose text names another claim (the USPTO dataset's rule for a dependent claim), words in all, of the first claim, and the least, mean and most of the independent and of the dependent claims, characters, the elements of the independent claims, the longest chain of dependencies, and the counts of "consisting", "or" and "selected from"; per claim the same counts for that claim. They are counted on request from the claim tree of the same claims (no language model, nothing stored), with counts_version, structure_version, generator, data_version, text_data_version and as_of, and the answer carries X-Data-Version and X-Text-Data-Version. It needs X-Api-Key and counts toward the monthly allowance like every data path. Its errors are the claim tree's: 404 with X-Status-Reason-Code NOT_FOUND for a patent the data does not have or one without claim text, 400 ERR_Q for a string that is not a patent number, 500 ERR_ES for a claim set over the work cap, 501 ERR_NOT_IMPLEMENTED with no long-text file. https://patentref.io/docs/claim-counts.html - New endpoint: POST /api/v1/structure/triage/ (and GET with the same fields as parameters), the triage table: up to 500 granted patents in one answer, as a list of numbers (a JSON list or pasted text) or as a search of the claims (words that must all be in one claim, "quoted phrases" kept as phrases, limit 1 to 500). Per patent: its expiry and maintenance-fee status, basis and reinstatement_possible, the values of GET /api/v1/lapse/status//; for each component the request names (up to 12; without them the table picks up to 6 terms its patents share) its position in the claims, every_independent, some_independent, only_dependent or absent, with the claims that mention it and the first mention; the terms its own claims introduce, by position; and each independent claim as a list of its parts (preamble, transition, elements and wherein clauses). Every quote carries claim, claim_id, start and end and is checked against the claim text before the answer leaves. output=csv gives the export, one row per patent, per component and per part. Built on request by the claim tree's deterministic parser (no language model, nothing stored), with a bounded cache per server process. One table at a time per key and a few at once on the server (429 with Retry-After and X-Status-Reason beyond that); a table stops reading claims after 20 s and then says complete false. It needs X-Api-Key and counts as one request toward the monthly allowance. https://patentref.io/docs/structure.html#triage - New pages: https://patentref.io/triage/ builds the table in the browser with your key, keeps your have and lacks marks on each part in the browser only and writes them into its CSV and JSON export; https://patentref.io/triage/example/ shows an example table without a key. - Changed on GET /api/v1/structure/claims// and in every answer read from a claim tree: the field of a term mention that says where its antecedent was found is now named found_in, with the same values (same_claim, dependency_chain or cited_claim); structure_version is "2", and generator names the parser's new version. Nothing else in a tree changed: the same claim text gives the same claims, parts and offsets. mode=structured on GET /api/v1/lapse/similar names structure_version "2" too. Read found_in, and cache under the new structure_version. - Changed: a string that is not a patent number on /api/v1/structure/claims// answers 400 ERR_Q with X-Status-Reason "Not a patent number: ''", reworded; the brief and the claim counts answer the same. - /api/v1/meta/status/ and status.json answer at once with the figures the server holds while it computes the next ones in the background, so a request no longer waits for them; the 30-day figures (requests_30d) are computed at most every 10 minutes, the others at most once a minute as before. The fields, their meaning and Cache-Control: public, max-age=60 are unchanged; requests_30d can be up to 10 minutes older than generated_at. - /api/v1/meta/status/ and status.json compute their next figures in the request that finds them more than a minute old, no longer in the background: a visit got the figures stored at the previous visit to that server process, so with few visits most answers showed figures hours old. That request takes a few milliseconds longer (about 3 s once every 10 minutes per server worker, for the 30-day figures); other requests meanwhile get the figures held. A 200 is never more than 10 minutes old: when the figures cannot be computed for 10 minutes, both answer 503 with Cache-Control: no-store (status.json {"error": "status temporarily unavailable"}) until they can. The fields, their meaning and Cache-Control: public, max-age=60 of a 200 are unchanged. - Documents only, the rest: openapi.json adds the three paths with their schemas, the brief's (PatentBrief, PatentBriefClaim, PatentBriefLine), the claim counts' (ClaimCounts, ClaimCountsPatent, ClaimCountsClaim) and the triage table's (TriageRequest, TriageTable, TriageRow, TriageStatus, TriageCell, TriageMention, TriageClaimParts, TriagePart); the paths it had are unchanged; in ClaimTreeClaim the term mention's property is found_in; info.description, the structure tag and the notes on X-Text-Data-Version and X-Status-Reason-Code name the new paths. llms.txt and llms-full.txt describe the three endpoints and the record page's anchors, the claim trees page https://patentref.io/docs/structure.html has sections on briefs, anchors and the triage table, and a new docs page, Claim counts, gives every count with the USPTO variable it follows and the comparison with the USPTO files on 1,000 random grants. The error index names the brief and the claim counts beside the claim tree. llms.txt, llms-full.txt, openapi.json and the docs pages carry this version. ## 1.20.0 (2026-10-29) - New parameter mode on GET /api/v1/lapse/similar. mode=structured, experimental, answers the patents whose claims introduce the most of the text's term keys: the noun phrases the claim tree's parser reads in the text, weighed by how rare their rarest word is in titles and abstracts. Candidates come from the title and abstract index (the text query, 40 deep, and the keys as phrases, 40); each candidate's claims are parsed on request by the claim tree's deterministic parser (no language model, nothing stored). Each neighbor has score, the weighed share of the text's keys found (1 means every key), and shared_terms with the claim's number and the mention's start and end in that claim's text. The answer carries method claim_term_keys, mode, term_keys, key_phrases, candidates, text_data_version and X-Text-Data-Version. With no long-text file in service mode=structured answers 501 ERR_NOT_IMPLEMENTED; a mode other than text or structured answers 400 ERR_Q. Without mode, or with mode=text, the answer is the same as before, byte for byte. The structured mode is experimental: the ranking is weakest where the shared terms are common short claim words, where near-identical patents tie, and where a text yields fewer than 3 term keys, as many chemistry abstracts do. No other endpoint changed. - /api/v1/meta/status/ and status.json: the outside figures (requests, the rates and the latency of requests_24h and requests_30d) now leave out PatentRef's own uptime probe key and its own beta test key too, as they already left out its operator key; those requests are counted in own_requests. - Documents only, the rest: openapi.json adds the mode parameter, the schema SimilarStructuredResponse beside SimilarResponse in the 200 answer, and the 501; the paths it had are otherwise unchanged. llms.txt and llms-full.txt describe the mode, and the Lapse fields page, https://patentref.io/docs/lapse.html, has a section on it. llms.txt, llms-full.txt, openapi.json and the docs pages carry this version. ## 1.19.0 (2026-10-29) - New endpoint: GET /api/v1/structure/claims// (the trailing slash is optional), the claim tree of one granted patent. It reads the claims the long-text file in service prints (the rows /api/v1/g_claim/ answers for the same patent) and returns each claim with its number, category, dependency and its basis, preamble, transition, elements, term mentions with the earlier mention each "the" or "said" phrase was matched to, and claim citations, every part with start and end offsets into the claim text, plus the relations between the parts and flags that note what the parser saw in the text and the data. The tree is built on request by a deterministic parser (no language model), with structure_version, generator, data_version, text_data_version and as_of, and the answer carries X-Data-Version and X-Text-Data-Version. It needs X-Api-Key and counts toward the monthly allowance like every data path. A patent the data does not have, or one without claim text (granted after the long-text file's last grant date), answers 404 with X-Status-Reason-Code NOT_FOUND; a string that is not a patent number answers 400 ERR_Q; a claim set over 1,000 claim rows or 1,000,000 characters answers 500 ERR_ES. No other endpoint changed. - Documents only, the rest: openapi.json adds the path with its schemas (ClaimTree, ClaimTreeClaim, ClaimTreeFlag) and the tag structure; the paths it had are unchanged. llms.txt and llms-full.txt describe the endpoint, and a new docs page, https://patentref.io/docs/structure.html, gives its fields, flags and an example. The error index names the endpoint's 404 under NOT_FOUND and its work cap under ERR_ES. llms.txt, llms-full.txt, openapi.json and the docs pages carry this version. ## 1.18.0 (2026-10-28) - GET /api/v1/meta/ answers with Cache-Control: no-cache, so a cache on the way asks the server before it reuses an answer. Before, it answered public, max-age=60, which let a cache keep a copy, and a copy kept from before a weekly data swap named the build before it. data_version in /api/v1/meta/ is the X-Data-Version of every answer, and generated_at says when the server produced the answer. - X-Data-Version on an answer that reads no data (a 403 without a key, the account endpoints, the API's own pages) names the data build in service at that moment. Before, right after a data swap it could name the build before the swap. An answer that reads data still names the build its body came from. - New files: https://patentref.io/brand/logo.png (512 by 512 pixels) and https://patentref.io/brand/logo.svg, the PatentRef mark, cached for a year. - Documents only, the rest: openapi.json names the mark in info.x-logo (alt text PatentRef, white background) and gives info.contact the name PatentRef, the email hello@patentref.io and the URL https://patentref.io/ (before, only the address of the status page). llms.txt, llms-full.txt, openapi.json and the docs pages carry this version. ## 1.17.0 (2026-10-27) - https://patentref.io/ answers a home page: what PatentRef is, the base URL in R and in Python, the free key, and links to the docs, the demo, the status page, the snapshot and the waitlist. Before, / answered a temporary redirect (302) to /docs/. /docs without the slash still redirects to /docs/. - New page: https://patentref.io/try/, a demo of four fixed requests that needs no key: one patent by its number, the grants to one assignee in one year, the claims of one patent, and its expiry and maintenance-fee status. Each is shown as the curl command a client sends with its own key, and https://patentref.io/try// runs it and shows the API's answer: the status, X-Data-Version and the JSON body a keyed client gets for the same request. The demo runs only these four, on an allowance shared by every visitor: 20 runs an hour from one address and 2,000 a day for everyone, then 429 with Retry-After. A run takes no key and no parameter (a request with X-Api-Key, Authorization or a query string answers 400 and runs nothing) and counts toward no account's allowance. - The name PatentRef in the header of the API's own pages (sign-up, waitlist, legal, record and error pages) links to the home page; before, it linked to the sign-up page. The status page keeps its link to itself. - Documents only, the rest: llms.txt, llms-full.txt, openapi.json and the docs pages carry this version, and llms.txt and llms-full.txt name the home page and the demo among the addresses that need no key. ## 1.16.0 (2026-10-26) - The record page https://patentref.io/p/ answers a request it has no record for (a patent number it cannot read, a patent it has no record of, a data version in v it never served) with an HTML page in English, with a title and a heading, in the same frame as the record pages, and the same status codes as before (404, or 503 when the status engine is not available). Before, these answers were one line of plain text. The record's JSON block on the page now wraps its long lines, so a phone screen shows it without scrolling sideways. - https://patentref.io/docs/errors/ and https://patentref.io/docs/errors/ answer a browser (an Accept header that prefers text/html to text/plain) with the same text as an HTML page. Every other client (no Accept header, */*, text/plain) gets the plain text byte for byte as before. Both answers carry Vary: Accept. - A request body over 64,000 bytes answers 413 for every caller, near the server or far from it, with or without a key, as the documents say. Before, a keyless POST of 64,001 to 65,536 bytes sent from a client far from the server could get 403 from the API instead, because the API's own body limit was 65,536 bytes; it is now 64,000, the web server's figure, so the API reads every such body to its end and the web server's 413 is the answer. - An address under https://patentref.io/docs/ that has no page answers 404 with a docs page that says so and lists the docs pages, with the site's Strict-Transport-Security header. Before, it answered 404 with an empty body. - Documents only, the rest: llms.txt, llms-full.txt, openapi.json and the docs pages carry this version. ## 1.15.0 (2026-10-26) - https://patentref.io/swagger-ui/, the interactive page upstream also served, now loads Swagger UI 5.32.15 pinned to that release, with Subresource Integrity on both files, under a Content-Security-Policy that allows only those two files, its one inline script, requests to patentref.io and data: images. It reads https://patentref.io/openapi.json. Before, it loaded unpinned Swagger UI 3 scripts with no Content-Security-Policy and read /static/openapi.json, which answered 404, so the page showed an error. The page sets no cookie. - https://patentref.io/robots.txt names a second sitemap, https://patentref.io/docs/sitemap.xml, which lists every page of the docs (the pages under /docs/, the error index and the legal pages). Before, it named only the registry's sitemap, which lists no record yet. - The registry is not open to outside records yet; its page now says so and its API refuses them: publishing (POST /registry/disclosures) and its preflight (POST /registry/disclosures/check) answer 403 with X-Status-Reason-Code ERR_NOT_OPEN ("The registry is not open to outside records yet.") for an account the registry is not open to, and store nothing; GET /registry/disclosures/terms has a new member, may_publish. https://patentref.io/registry/ says "The registry is not open to outside records yet." in place of "Publishing is free with a PatentRef account". Records already published read as before. - Documents only, the rest: openapi.json, llms.txt and the docs say that a PatentsView client moves by changing the base URL and adding a key (before, "by changing only the base URL"; a PatentRef key was always needed). Every docs page has its own title and description, and the page for moving from PatentsView starts with the base URL change and the key. A new docs page, https://patentref.io/docs/snapshot.html, links the snapshot on Zenodo (DOI 10.5281/zenodo.23250455, the newest version 10.5281/zenodo.23612407) with its files, their SHA-256 and the download links. llms-full.txt, llms.txt and openapi.json give the last grant date the long text covers: 2025-12-30 for claims, brief summaries, detailed descriptions and drawing descriptions (long-text build 20261006.4; before, llms-full.txt said "claims of every grant year"); patents granted after it have no long text yet. They no longer name an MCP server of PatentRef's own, which is not published. ## 1.14.0 (2026-10-26) - POST /api/v1/meta/keys/ takes an optional "source" in the body: the campaign code of the sign-up link (its utm_source; 1 to 32 letters, digits and hyphens). When the request creates a key, one is added to that ISO week's count for the code. Nothing is stored with the key or the account, the answer is the same with or without it, and a code outside the rule is ignored. Counting starts on the day Privacy Policy beta-4 takes effect, 14 days after this version is deployed (the date is on the policy's first line). - The sign-up page https://patentref.io/api/v1/meta/signup/ reads utm_source from its own address, keeps it through the email confirmation link and sends it as "source" with the first key. https://patentref.io/signup and /signup/ keep the query string through their redirect; before, the redirect dropped it. - New page: https://patentref.io/waitlist/, one form with an email address and three choices (Lapse alerts and lists, Rules updates, Registry opening). It is double opt-in: a POST mails a confirmation link, GET /waitlist/confirm/ shows a button and a POST there confirms. Every waitlist mail carries List-Unsubscribe and List-Unsubscribe-Post (RFC 8058) with a https://patentref.io/u/ address, and a POST there takes the address off the waitlist. A client address may post 5 times an hour and an email domain 200 times a day (above that, 429 with Retry-After); a disposable email domain answers 400. The form opens on the day Privacy Policy beta-4 takes effect; until then the page gives that date and a POST answers 403. - The status page https://patentref.io/api/v1/meta/status/ shows a notice while a legal document is posted ahead of its effective date, with the document's own summary of what is new: for the 14 days from this deploy, the Privacy Policy beta-4. - Documents: the Privacy Policy beta-4 (https://patentref.io/docs/legal/privacy) and the processor register beta-4, posted on the day this version is deployed and in effect 14 days later (both dates are on each page's first line); the legal pages and the unsubscribe page name hello@patentref.io as the contact address until the legal@, privacy@ and abuse@ mailboxes are live (before, aaron@omnipoolbuilders.com). ## 1.13.0 (2026-10-25) - New path: /api/v1/patent/otherreference/ (with or without the trailing slash, GET and POST) answers exactly what /api/v1/patent/other_reference/ answers. It is the path upstream used before its release 2.2.0 (2024-11-06), and the PatentsView code examples notebook still names it in its endpoint table. Before, it answered 404. - /docs/errors/ERR_Q now gives the size limits as the service applies them: q over 16 KB (16,384 bytes) in a POST body answers 400 ERR_Q; a request body over 64,000 bytes answers 413 with an empty body and no X-Status-Reason-Code, from the web server in front of the API (some pages said 400 ERR_Q for that); a GET request line over 4,094 bytes answers 400 with an HTML page and no X-Status-Reason-Code. Nothing about these limits changed; the pages now say what was already answered. - Documents only, the rest: llms-full.txt, llms.txt, openapi.json and the docs pages now say how a GET query string is read (raw JSON works except for spaces, "+", "&", "#" and "%"; percent-encoding always works), the trailing-slash rule (a list route answers with or without it; a detail route without it answers 301), that a number field takes a numeric string ("2021"), the country code format (ISO two-letter codes in capitals on the inventor, assignee and location fields: GB, not UK), the URL form of the link fields and that a link comes back beside its id, that inventors.disambiguated and the other added fields come back only when f names them, and the order of the rows in a nested group (the order of their source). ## 1.12.0 (2026-10-25) - In the lapse group on /api/v1/patent/ and /api/v1/patent/{patent_id}/ (f naming "lapse" or "lapse."), fwd_early, fwd_late and sleeper_flag also count the citations made by the weekly grants added after the PatentsView release (the USPTO weekly grant files from 2026-01-06 on). Before, they counted only the citations in PatentsView's file, which ends 2025-12-30, so a patent that 2026 grants cite could read as quiet. They still count US utility patents citing the patent, as before. - The values change with the first data build after this version; until then the group answers as before. ## 1.11.0 (2026-10-23) - POST /api/v1/meta/keys/ mints or rotates a key only once the PatentRef Terms of Service, Privacy Policy and Acceptable Use Policy are accepted (https://patentref.io/docs/legal/terms, /docs/legal/privacy, /docs/legal/acceptable-use). Send {"terms_version": "beta-2"} in the body after reading them (the version the 403 names), unless the account accepted that version at sign-up (the sign-up page and the registry's sign-up store it) or with its last key. Otherwise the answer is 403 with X-Status-Reason-Code ERR_TERMS and a body {"error": true, "terms_version", "terms": {"terms", "privacy", "acceptable_use"}, "how"}. Before, an empty body minted a key. A POST while a key is active still answers 200 with that key's record. - The sign-up page https://patentref.io/api/v1/meta/signup/ has a required box with the three links in its sign-up form and above its key buttons. - The key record (201 and 200 answers of POST /api/v1/meta/keys/, each key of GET /api/v1/meta/keys/) has a new member, terms_version: the version accepted when the key was minted, null for a key minted before. - Keys minted before keep working on every path; only a new key or a rotation asks. https://patentref.io/docs/errors/ERR_TERMS explains the code. ## 1.10.0 (2026-10-21) - New fields, returned only when f names them: the assignee's names as printed on the grant, beside PatentsView's disambiguated names. On /api/v1/patent/: assignees.raw_assignee_organization, assignees.raw_assignee_individual_name_first and assignees.raw_assignee_individual_name_last, then on every row of the assignees group. On /api/v1/assignee/: raw_assignee_organization, raw_assignee_individual_name_first and raw_assignee_individual_name_last, the names printed on the assignee's most recent patent. The disambiguated fields are unchanged: assignee_organization is PatentsView's one label for a whole cluster of spellings, which can differ from the grant (US 6859933 is printed "Samsung Electronics, Co., Ltd."; its label is "SAMSUNG DISPLAY CO., LTD."). The names come from PatentsView's g_assignee_not_disambiguated file and, for weekly grants, from the grant full text. - Nothing else changes for a request that does not name them: the default fields and a whole group in f ("assignees" or "assignees.*") answer the upstream fields only, as before. q or s on one of them answers 400 ERR_Q (X-Status-Reason "Invalid field: is returned with f only; it cannot be queried or sorted in this version"). - They are null where the bulk data has none (an individual has no organization, an organization no individual names) and in a data version built before them; the first data build after this version carries them. ## 1.9.1 (2026-10-21) - Documents only. https://patentref.io/docs/ is the docs site: a quick start, the query grammar, one page per endpoint with its routes, response key, default fields, sort and options, sortable fields, nested groups, every field with its type and search kind and an example request (each with a JSON twin beside it, for example /docs/endpoints/patent.json), the Lapse fields, the known differences from the upstream PatentSearch API, moving from PatentsView, keys, limits and errors, the 31 contract examples, and data, licenses and attribution. The pages are generated from the same sources as openapi.json and llms-full.txt and say nothing those do not. Every page shows the data version it was generated against and, in a browser, the version in service. /docs/errors/ and /docs/legal/ are unchanged. - https://patentref.io/ and https://patentref.io/docs now redirect to /docs/ (before, / and /docs answered a temporary redirect to the sign-up page, and /docs/ did too). The sign-up page is linked from every docs page. - robots.txt allows /docs/ (it allowed /docs/errors/, which /docs/ includes). llms.txt and llms-full.txt name the docs site. ## 1.9.0 (2026-10-21) - The legal documents are pages: https://patentref.io/docs/legal/terms (Terms of Service), /docs/legal/privacy (Privacy Policy), /docs/legal/acceptable-use (Acceptable Use Policy), /docs/legal/dmca (copyright complaints and the designated agent, U.S. Copyright Office registration DMCA-1083075) and /docs/legal/processors (the providers that process personal data and their data processing agreements). Each is also served as Markdown at the same address with .md added (text/markdown), and /docs/legal/ lists them. Before, these addresses answered 404. - Every page (the sign-up page, the status page, the record pages and the legal pages) has the same footer, which now links the four documents. The scrolling tables on the status page and the record page can be reached and scrolled with the keyboard. - New: https://patentref.io/u/, the unsubscribe address that mail PatentRef sends will carry in its List-Unsubscribe header (RFC 8058). A POST with the body List-Unsubscribe=One-Click unsubscribes that address from that kind of mail, with no sign-in; a GET shows a page with one button. An unknown token answers 404. No mail carries one yet: the only mail today is the sign-up and sign-in mail, which is not something to unsubscribe from. - New: POST /api/v1/meta/email/events/, the endpoint where the mail provider reports bounces and complaints, so that a bounced address is not mailed again. It accepts only requests signed by the provider; others answer 400 or 401, and it answers 503 until the provider's signing secret is installed. ## 1.8.0 (2026-10-20) - New paths under /api/v1/rules/ (X-Api-Key, counted like every data path): GET /api/v1/rules/ (the index: version, offices, tools, vocabulary), /api/v1/rules/rep_required/, /fee_schedule/, /route_windows/, /pph_routes/, /ai_use_statement_required/, /grace_period/ and /changelog/. Each answers rows of the rules dataset (US, EP, CN, JP, KR, AU and the PCT), every row with the official source it was read from, a verbatim quote and its effective dates, plus rules_version and as_of, and the header X-Rules-Version. A parameter that names an application, a patent or a priority date answers 400 ERR_Q. - GET /api/v1/meta/ has a new member, rules_version: the version of the rules dataset in service (null when it cannot be read). ## 1.7.0 (2026-10-19) - /api/v1/meta/status.json: requests_24h and requests_30d have two new members. not_served counts the documented 501 answers of the endpoints whose data set is not in this release (the deferred list of /api/v1/meta/); those answers are no longer counted in server_errors, server_error_rate or error_rate. own_requests counts the requests the service sends to check itself; they are no longer in any of the other figures (counts, rates, latency). For example, the 24 hours to 2026-10-19 20:47 UTC read 38 server errors of 539 requests (7.05 percent); all 38 were documented 501 answers or the service's own checks, so the same requests now give 0 server errors. The status page shows both counts in its table. - The record page /p/ shows the patent's family outside the US once the data in service carries it: the publications outside the US that Google Patents Public Datasets puts in the same family (office, number, kind, publication date; the first 200), the credit line "Family data from Google Patents Public Datasets, used under CC BY 4.0." in the block and the footer, and a link to the patent's family on USPTO Global Dossier. The legal status of those publications is not shown. Before, the page had no family block; it has none until a data release carries the family tables. - Every answer from patentref.io carries Strict-Transport-Security: max-age=31536000; includeSubDomains. Before, none did. - https://patentref.io/robots.txt answers 200 with text/plain (before, 404): it allows the documents (llms.txt, llms-full.txt, openapi.json, changes.txt, LICENSES.md, /docs/errors/, the sign-up and status pages) and the registry's record pages (/r/ and /registry/r/), disallows /registry/publish, /registry/mine, /api/v1/meta/keys, /api/v1/meta/usage and /api/v1/create-key, and names the sitemap https://patentref.io/registry/sitemap.xml. ## 1.6.0 (2026-10-19) - GET /api/v1/meta/health/ also answers HEAD, with the status the GET would give and no body; before, HEAD answered 405. UptimeRobot's HTTP check sends HEAD first. - /api/v1/meta/status.json has two new members. external_check is UptimeRobot's check of /api/v1/meta/health/ from its own network, as the box last read UptimeRobot's record (state, state_since, last_check_at, last_check_ms, interval_minutes, checks_24h, regions, last_incident, incidents, read_at, fresh); a fresh reading of "down" makes the state "degraded". uptime_official is the uptime figure since 2026-10-06 03:47 UTC: the down time the GitHub probe recorded until 2026-10-15 02:57:08 UTC, and from then on the incidents UptimeRobot reports (uptime_percent, down_minutes, down_minutes_before_switch, down_minutes_after_switch, switch_at, incidents_after_switch, note). The status page's first tile now shows uptime_official.uptime_percent; before, it showed uptime.uptime_percent, the GitHub probe's own figure, which status.json still carries. ## 1.5.0 (2026-10-13) - expiry_date_estimated and expiry_status: an international application's number that a USPTO record writes without one or both of its slashes (PCTGB9300583, PCTGB93/00583) is now read as the same number as PCT/GB93/00583, with the year it names, and PatentRef's sentences and record pages write it with the slashes (the record page also shows how the record writes it). So the 1.4.0 rule applies to it: a parent row with such a number and a date outside that year no longer counts for the 20-year term, and the filing date the record of the parent's national stage gives counts instead, also where that record writes the number without the slashes. For example US 6373144: term end 2019-08-04, 20 years from its parent PCT/DE99/02420 (written PCTDE9902420), filed 1999-08-04 by the record of its national stage; before, 2018-08-19 from the 1998-08-19 its own row gives. US 7377652: expired_term, term end 2022-02-27, from its parent PCT/CA02/00255, filed 2002-02-27 by the record of its national stage, which writes the number PCTCA02/00255; before, no term end, and a sentence that said PatentRef held no other USPTO record that gave that application's filing date. US 6560944: unknown, since its parent PCT/GB93/00583 (written PCTGB9300583), a 1993 number, carries 1983-03-22 and no other record PatentRef holds dates it; before, expired_term from that date. - On data version 20261013.1 this reads 13,035 more parent rows as international applications, and 149 of them give a date outside their number's year (2,736 rows of 2,666 patents in all). 141 term ends change: 17 to another date and 124 to none. 6 statuses change: 4 from expired_fee_nonpayment to unknown and 2 from expired_term to unknown. Of the 1,150 patents whose parent's filing date stays unsettled, 922 have a status that holds on every possible date and no term end, 213 read unknown, and 15 withdrawn, design, reissued or listed patents keep their status. - The pages of the Django admin and of a Google login that the API's upstream code carried (/admin/, /login/, /complete/, /disconnect/) are gone; those paths answer 404. PatentRef accounts are made on the sign-up page. - 1.4.0's third bullet now gives the counts the API serves on that data: 1,053 term ends to another date and 1,020 to none (it said 1,051 and 1,022), 1,034 patents left unsettled with 207 unknown (it said 1,036 and 209), and 70 moves from active to expired_term, 55 from expired_term to expired_fee_nonpayment, 81 from active to unknown and 55 from expired_term to unknown (it said 69, 54, 82 and 56). The first count missed the national stage records of US 8243876 and US 8892399, which the API finds. ## 1.4.0 (2026-10-13) - expiry_date_estimated and expiry_status: a parent application's filing date that the USPTO record itself contradicts no longer counts for the 20-year term. An international application's number names the year its receiving office received it, which is the year it was filed unless a defect moved the filing date (PCT/US2005/039541 was filed in 2005); numbers with a two-digit year were used only up to 2003 (a later number written that way, such as PCT/EP04/001145, is read as a number of 2004 only when the row's date falls in 2004, and otherwise names no year), and no international application was filed before 1978-06-01; a US application's serial number begins with its series code, and the applications of each series were filed in known years. Where a parent row gives a date outside those years, or a number that names no possible year, the filing date another USPTO record PatentRef holds gives for the same application counts instead: another row of the same patent's record, the international filing date in the record of the parent's national stage, or the filing date in the record of the patent granted on the parent. PatentRef also does not use a US parent date before 1950. For example US 9527819: expired_term, term end 2025-11-02, 20 years from its parent PCT/US2005/039541, filed 2005-11-02 by the record of its national stage; before, active, term end 2028-07-22 from the 2008-07-22 its own row gives. US 9087778: active, term end 2032-10-19, from its parent 13/655,875, filed 2012-10-19; before, expired_term, term end 1940-02-10 from the row's 1920-02-10. - Where PatentRef holds no other USPTO record that gives that parent's filing date and the parent could be the earliest one, the record gives no single term end, and expiry_date_estimated is null. expiry_status is then the status the record's dates give on the date the row gives, when that date is a possible filing date, and on every filing date the parent's number allows (the year or the series years it names; any day from 1978-06-01 when it names no possible year or a serial number its office never reached in that year; never after the patent's own filing). The plain sentence names the parent application, the date and why the date does not fit, and says on which dates the status holds, for example: "As of 2026-10-06, the USPTO record for US 10015129 shows no unresolved maintenance-fee lapse; it gives parent application PCT/CN2014/073309 the filing date 2013-03-12, which is not in the year that application's number names, and PatentRef holds no other USPTO record that gives that application's filing date, so no single term end can be computed, but on that date and on any filing date that application's number allows, the term end computed from the record's dates has not passed (data version 20261006.5)." Where those dates give different statuses, expiry_status is unknown, for example: "As of 2026-10-06, the USPTO record for US 11468088 does not settle its status: it gives parent application PCT/EP2006/063796 the filing date 2009-10-21, which is not in the year that application's number names, and PatentRef holds no other USPTO record that gives that application's filing date (data version 20261006.5)." The record page's term-end row names the application, the date and why it does not fit. - On data version 20261006.5, 2,587 parent rows of 2,519 patents give such a date. 2,073 term ends change: 1,053 to another date and 1,020 to none. Of the 1,034 patents whose parent's filing date stays unsettled, 813 have a status that holds on every possible date and no term end, 207 read unknown, and 14 withdrawn, design, reissued or listed patents keep their status. 460 statuses change: 70 from active to expired_term, 68 from expired_term to active, 60 from expired_fee_nonpayment to expired_term, 55 from expired_term to expired_fee_nonpayment, 81 from active to unknown, 55 from expired_term to unknown and 71 from expired_fee_nonpayment to unknown. ## 1.3.0 (2026-10-12) - expiry_status: a patent whose maintenance fee went unpaid now reads expired_term, not expired_fee_nonpayment, when its computed term end came before the fee's 6-month grace period ran out: the term ended first. expiry_basis keeps fee_lapse: and lapse_date is unchanged; reinstatement_possible is false, reinstatement_basis is "35 USC 154: term ended (the term ended before the fee lapse)", and the plain sentence is the expired_term sentence. For example US 8741605: expired_term, term end 2024-01-14 (20 years from the filing of its parent application on 2004-01-14); before, expired_fee_nonpayment with the fee record's entry of 2026-07-06. On data version 20261006.5 this moves 83,587 patents from expired_fee_nonpayment to expired_term (229 of them because of the related-publication parent rule below). - Where the USPTO 35 USC 156 list gives an earlier term end than the record's own dates and the record shows no terminal disclaimer, the later of the two is the term end compared with the fee's grace period and used for reinstatement_possible, and while only one of the two has passed expiry_date_estimated is null. US 9580461 (the list's dates add up to 2023-08-12, the record's to 2032-04-04, and the grace period of its unpaid fee ran out 2025-02-28) stays expired_fee_nonpayment; its reinstatement_possible changes from false to "unknown" and its expiry_date_estimated from 2023-08-12 to null. - expiry_date_estimated: a parent international application that the record lists as a related publication now counts as a parent for the 20-year term, as a continuation, division or continuation-in-part parent does. For example US 6459001: 2017-03-20, 20 years from its parent international application filed 1997-03-20; before, 2021-01-25. On data version 20261006.5 this moves 4,521 term ends, all earlier, most by 2 to 5 years; on its own it changes no status. - US 7511131 is on the USPTO list of patent terms extended under 35 USC 156, where its original expiration date is printed "12/13/22025". It is now read as 2025-12-13, the term end the record's own dates give, and its term end is 2027-01-29: that date plus the list's 412 days of extension. Before, the list row was left out and the term end was 2025-12-13. Its status stays expired_fee_nonpayment, and reinstatement_possible changes from false to "unknown" because the term end has not passed. The record page shows the printed date beside the reading. - Responses no longer carry the header "Server: gunicorn". ## 1.2.0 (2026-10-12) - Long text: /api/v1/g_claim/, /g_brf_sum_text/, /g_detail_desc_text/ and /g_draw_desc_text/ also send X-Text-Data-Version, the data_version of the long-text file the rows came from (text_data_version in GET /api/v1/meta/health/). X-Data-Version still names the search file. Cache long text under X-Text-Data-Version. - The plain sentence of GET /api/v1/lapse/status// and of the record page /p/ says the term end is computed from the dates in the USPTO record, for example: "As of 2026-10-06, the term end computed from the dates in the USPTO record for US 5000000 is 2009-05-15 (20 years from filing), a date that has passed, and the USPTO list of patent terms extended under 35 USC 156, updated through 2026-09-08, does not name this patent (data version 20261006.5)." Before, it said the record shows the term ended. The fee-lapse sentence gives the date of the maintenance-fee record's expiry entry; the withdrawn sentence says withdrawn from issue; the unknown sentence says no term end can be computed from the record's dates. - expiry_date_estimated and expiry_status: for a continuation, division or continuation-in-part the 20-year term counts from the filing date of the earliest parent application the record lists (35 USC 154(a)(2)); before, it counted from the patent's own filing date. Such patents get an earlier date, and some change from active to expired_term (for example US 11086507: 2025-12-23, expired_term; before 2040-07-21, active). On data version 20261006.5 this moves 1,758,476 term ends, and 86,278 patents change from active to expired_term. - A national stage under 35 USC 371 counts from its international filing date (35 USC 363) where the record gives its 371 date as the filing date; a patent on the USPTO list of patent terms extended under 35 USC 156 (retrieved 2026-10-11, updated through 2026-09-08) takes the list's original expiration date plus the extension, with the new basis code pte_156:, and its plain sentence gives the list's original expiration date and extension and the date they add up to; where the list's date has passed and the term computed from the record has not, or the other way round, expiry_status is unknown and the sentence gives both; a patent withdrawn from issue gets no term end and no term codes; a term end on the as_of date itself reads as not yet passed. The expired_term sentence of a patent not on the list says the list does not name it, or names its reissue. On data version 20261006.5: 72,743 term ends move by a 371 date; 1,112 by the 156 list, with 19 patents changing from active to expired_term, 8 from active to unknown (the list and the record disagree), 61 from expired_term to active and 53 reissues from unknown to expired_term (38) or active (15); 19,415 withdrawn patents lose their term end; 143 patents whose term end is the as_of date itself change from expired_term to active. - GET /api/v1/meta/: deferred lists every data set the files in service lack, each with the routes that answer 501: publications, cpc_classes, cpc_subclasses, uspc_mainclasses and wipo today (before: publications only). delta_note is reworded. - A 501's X-Status-Reason says where each patent carries the same facts for the four classification lookups (cpc_current, cpc_at_issue, uspc_at_issue and wipo on /api/v1/patent/), and "pre-grant publications are deferred to a later build" on every pre-grant route. - openapi.json: x-patentref-kind on every record field. A link field takes the kind of the id behind it (keyword: q matches the id, not the URL; none: no search field), and the lapse group's fields are f-only (returned when f names them; q or s on them answers 400 ERR_Q). The X-Status-Reason-Code header lists NOT_FOUND (a v that never existed on /api/v1/lapse/status/). info.version follows the rule above. - /docs/errors/: ERR_Q lists the same rules as llms-full.txt section 2 (a sort on a text field without a keyword form, no q on a list endpoint, q or s on the lapse group), and the index says which codes the X-Status-Reason-Code header carries. - This list, linked from llms.txt. ## 1.1.0 (2026-10-11 07:32 UTC) - disambiguated (the inventors, assignees and attorneys groups of /api/v1/patent/) comes only when f names it, for example "inventors.disambiguated", and then on every row of the group: true on PatentsView rows, false on weekly-grant rows. A whole group in f ("inventors") carries the upstream fields only. Before, weekly-grant rows of a whole group carried "disambiguated": false and PatentsView rows did not. - openapi.json: q, f, s and o are JSON parameters with schemas (Query, Fields, Sort, Options), and q is declared required on the list endpoints other than the lookups. The server already answered 400 ERR_Q without q. Record fields carry no maxLength, and every route outside /patent/ declares the 501. - info.version still read "v1". ## 1.0.0 - Everything before 2026-10-11 07:32 UTC (info.version read "v1").