One search result from our US primary law API now carries 148 fields, and not for completeness's sake. Text plus a citation renders a section on a page and supports almost nothing else. Every hard question your product will eventually ask (is this current, what changed, what does it point at, where exactly did it come from) is answered by metadata, and an API that doesn't carry it leaves you reconstructing it from the text with a regex. That is where wrong answers are born. This post walks 128 of those fields in nine families (the other 20 are the raw-text twins of date fields, body, sourceUrl and a few narrow ones) and, for each family, answers the only question worth asking: what can you now build that you could not build before.
Reviewed and corrected on 12 October 2026. This is general information, not legal advice.
TL;DR
- A thin legal API returns text, a citation, and a link. That supports a reader view, not a staleness banner, a citation graph, a change feed, or a checkable provenance claim.
- The 128 core fields group into nine families, and each family maps to a product feature rather than a schema aesthetic.
sourceCharStartandsourceCharEndare the sleeper fields. Where populated, they mark where the text begins and ends in the source document, so you can reconcile an extraction against the original PDF. They are null on many rows (all three rows we checked on 12 October 2026), so read them as a corpus-specific bonus, not a guarantee.- Most fields are null on any given row, by design. A comment close date means something for a Federal Register proposed rule and nothing for a state constitution.
- Amendment history and
asOfanswer different questions. The amendment fields tell you when a section last moved.asOf=YYYY-MM-DDon the body endpoint returns earlier text, as a held published edition or a reconstruction from recorded changes. A change feed and per-section diffs on a watched source sit alongside both. - The
fieldsparameter prunes a response, always keepsactIdandcitation, and rejects an unknown name with 422 instead of dropping it quietly.
Your compliance app shows a regulation with a banner reading "Updated 3 days ago." A customer asks whether that means the rule itself changed 3 days ago. What does the banner actually tell them?
This is one post in our legal data infrastructure series.
For related coverage, see What a Legal Data API Should Guarantee: The Schema Contract for the tier argument behind these families, Legal Citation Resolution: Turning a Cite Into the Right Section, Every Time, and Amendment History and Point-in-Time Law: What a Legal API Can and Cannot Tell You.
The thin response, and what it costs you
Here is the shape most legal APIs return.
{
"citation": "42 U.S.C. 1983",
"title": "Civil action for deprivation of rights",
"text": "Every person who, under color of any statute...",
"url": "https://uscode.house.gov/..."
}
You can build a reader view on that. You can't build anything that has an opinion about the row.
Is this text current, and current through what date? When did it last change? What does it cite, and what cites it? If this section moved, where did it go? Is the comment period still open? The thin response goes quiet on all of it.
So you parse the text: pull a year out of a trailing history note, regex the cross references, guess the hierarchy from the citation string. That works on the corpus you tested and breaks on the next state, which prints its history note in a different shape, or prints none.
A short history: the citation graph before computers
Half of the families below exist to answer one old question: what happened to this law after it was written? Lawyers have had a tool for that since 1873. LexisNexis, which runs the service today, tells the story on its own site. Shepard's Citator "was first published in 1873 by Frank Shepard, a salesman in Chicago." In his sales meetings he noticed "that every attorney was doing the same thing: keeping notes of case treatment in the margins." The first pamphlets were made for Illinois attorneys and "later evolved into adhesive annotations that could be put directly into casebooks." (LexisNexis, Shepard's Citation Guide, Part 1)
So the first citation graph was a pile of stickers. A Hacker News commenter described the book-set era this way in 2022: you looked up a case or statute and Shepard's listed the later authorities that cited it, and for each whether it followed or overruled yours. The same comment sums up the whole system in one line: "It was essentially a database system, implemented entirely in books." (tzs, Hacker News, July 2022)
Software didn't make the question easier. In a 2017 thread titled "Why isn't there a Google for the law?", a commenter who said they had worked on Google Scholar and were CEO of Judicata argued that the hard part wasn't the links between documents: "the real challenge for legal research is extracting structure out of the law." (igurari, Hacker News, January 2017) That is a fair one-sentence summary of why a response with status, amendment, relationship and provenance fields beats a response with only text. The structure has to be captured somewhere, and a typed field at ingest is a better place than a regex in your app.
The nine families, and the feature each one unlocks
Corpus scale for context: more than 5.3 million distinct sections indexed as more than 20 million retrieval passages across 56 jurisdictions (50 states, DC, Puerto Rico, Guam, the Northern Mariana Islands, the US Virgin Islands and American Samoa), plus federal law. One search result over that corpus publishes 148 fields, 128 of them walked below and each named in the response field reference.
Identity: 7 fields
| Group | Fields |
|---|---|
| Primary key | actId |
| Citation forms | citation, citationShort, alternateCitations |
| Human-readable identity | sectionNumber, sectionTitle, displayLabel |
What this lets you build: a cache, a dedup key, and a cross reference that survives a rebuild. Real ids look like USC_T42_C21_S1983 and SAL_PL116-136_DVA_TII_S1109 (CARES Act section 1109). They are stable but not guessable, so you store one from a search or resolve response rather than constructing it.
alternateCitations is the underrated one. Two lawyers can cite the same provision three ways, and a matcher that only knows the canonical string treats those as three different provisions.
Hierarchy: 22 fields
| Group | Fields |
|---|---|
| Title level | title, titleName, titleNumber, topLevelTitle, subtitle, subtitleName |
| Chapter level | chapter, chapterName, subchapter, subchapterName |
| Part level | part, partName, subpart, subpartName |
| Article and subject | articleNumber, articleName, subject, subjectNumber |
| Rendered position | breadcrumb, displayPath, parent, volume |
Twenty-two fields for "where is this in the code" sounds excessive until you normalize across 56 jurisdictions. Some states nest title, chapter, article, section. Some use subtitle and part, some use subject numbers that map to none of it.
What this lets you build: a browsable code tree and a working "show me the rest of this chapter". With parent and breadcrumb you render the path above a section with no second call. With chapter plus titleNumber you fetch the siblings, and the divisions endpoint (GET /us/statutes/divisions?corpusType=STATE&state=XX) walks the same tree top down.
Concretely: a compliance product showing one regulation can put a "other sections in this subpart" strip under it, because subpart and subpartName are on the row already. Without them you are parsing the citation string and hoping the state's numbering is regular. It isn't.
Provenance and format mirrors: 16 fields
| Group | Fields |
|---|---|
| Canonical page | externalUrl, publisherKey |
| Format mirrors | stateHtmlUrl, htmlUrl, pdfUrl, xmlUrl, textUrl, docxUrl |
| GovInfo copies and ids | govInfoHtmlUrl, govInfoPdfUrl, packageId, granuleId |
| Exact span in the artifact | sourceCharStart, sourceCharEnd, sourcePageStart, sourcePageEnd |
The four offset fields are the most interesting in this family, with a caveat.
A link is a claim. It says "this text came from that page," and the reader either takes your word for it or opens the page and hunts. Offsets replace the claim with an address: the text starts at sourceCharStart and ends at sourceCharEnd in the source document, and for a PDF source sourcePageStart and sourcePageEnd give the page range, so a citation checker can land a reviewer on the right page of the official print. The API reference documents sourcePageStart as 100 percent populated on the Federal Rules. On the other rows we pulled on 12 October 2026 (a US Code section, a Statutes at Large section and a Maryland insurance bulletin) all four were null. Even within the Federal Rules it varies by row: Fed. R. Evid. 801 and Sup. Ct. R. 13 and 14 carried page numbers that day, while Fed. R. Civ. P. 12, Fed. R. Crim. P. 12 and Fed. R. Evid. 802 and 807 returned null. Check which rows populate them before you design around them.
The format mirrors, documented per corpus, matter for a different reason. A publisher's HTML and PDF of the same rule aren't always identical, so an export can attach the format you cite rather than the convenient one.
Currency and status: 14 fields
| Group | Fields |
|---|---|
| Currency as the publisher states it | currentThrough, currencyYear, currencyNote, edition |
| Effect window | effectiveDate, expirationDate, originalEnactmentDate, priorEffectiveDates |
| Publication dates, one per corpus convention | issueDate, publicationDate, releaseDate, reviewDate |
| Status | goodLawStatus, actStatus |
What this lets you build: an honest staleness banner. Not "updated recently," which is about you, but "current through January 6, 2025 per the publisher," which is about the law. Only one of those is useful to a lawyer.
goodLawStatus and actStatus carry a design decision worth copying. Statutes at Large items are law as enacted, a record of what Congress passed, so they carry actStatus: "enacted" and goodLawStatus: "unknown" on purpose. Calling an old public law current law would be a lie dressed as a field value.
Four publication date fields looks redundant until you notice that a Federal Register document has a publication date, agency guidance has an issue date, and a court rules compilation has a release date. Collapsing them destroys a distinction the user needs.
Amendment history: 8 fields
| Group | Fields |
|---|---|
| Most recent amendment credited | lastAmendedYear, lastAmendedDate |
| Every credited year, and how many | amendmentYears, amendmentsCount |
| The publisher's own history text, as printed | amendmentNote, amendmentHistory, history, sourceCredit |
What this lets you build: a change timeline per section, and a currency filter that tracks the law instead of your own rebuild date. The yearFrom and yearTo search parameters filter on a section's last amendment year as the publisher credits it (falling back to its effective year, or to the publication year for corpora dated that way), so "show me everything in this chapter touched since 2020" is a query rather than a project.
Read this family precisely, because it is where vendors oversell. The amendment fields are an amendment record. One citation maps to the current text, and the version information sits in the amendment credits around it. You can see every amendment year the publisher credits on a section. To read what the text said on a date, pass asOf=YYYY-MM-DD to the body endpoint. Where we hold the publisher's printed editions (the CFR annual editions, for one) you get the edition that governs your date. Coverage of held editions is per corpus, and for the US Code most historical dates fall outside the editions we hold. Elsewhere the earlier text is rebuilt from the first change we observed after it, and isBounded marks an answer that rests on when capture began, so a date before capture can come back unavailable. What a legal API can and cannot tell you about point-in-time law goes through that boundary in full.
Three causes, and only one is a wrong answer: the note was never captured, the note was captured but never parsed into a year, or something on the page that isn't the history got read as if it were. A missing year is often a publisher property rather than a pipeline failure, because some state publishers print no amendment credit at all. Delaware is a clear case: its history lines cite the session-law volume and chapter (on delcode.delaware.gov the version of Title 13, section 1301 in effect on 12 October 2026 ends "70 Del. Laws, c. 186, § 1") and print no calendar year, so a year has to be derived from the volume.
That is also why yearFrom and yearTo drop sections that carry none of the dates the filter reads once either bound is set. A section with no date can't honestly sit inside a year range.
Relationships between provisions: 15 fields
| Group | Fields |
|---|---|
| Outbound references | crossReferencesUsc, crossReferencesCfr, relatedCitations, referencedShortTitles |
| Enacting instruments | publicLaws, publicLawCites, adoptingCitations |
| Statute to regulation, both directions | statutoryAuthority, lawImplemented, implementingRegulations |
| Replacement chain | supersedes, supersededBy, supersessionActions |
| Provision moved | renumberedTo, transferredTo |
What this lets you build: a citation graph, and a regulation-to-statute jump. statutoryAuthority and lawImplemented let a user reading a rule click through to the statute that authorized it in one hop, with no hand-maintained lookup table. Run it the other way with implementingRegulations and a statute page lists the rules built on it.
renumberedTo and transferredTo solve a problem that silently corrupts legal products. A provision that moved isn't gone, but to a system keyed only on the old citation it looks identical to a repeal. The saved search breaks, the alert stops firing, and nothing errors.
Worked example: a policy team tracks a statute and wants every regulation that names it as authority. With statutoryAuthority populated that is a filter. Without it, it is a string search across more than 1.5 million state regulation sections that misses every rule citing the statute in a form you didn't anticipate.
The Federal Register block: 13 fields
| Group | Fields |
|---|---|
| Where it sits in the FR | frVolume, frStartPage, frEndPage, federalRegisterCitations |
| Rulemaking identity | frDocketIds, frRegulationIdNumbers, frRelatedDocuments, frSignificant |
| Dates you can act on | frEffectiveOn, frCommentsCloseOn |
| Corrections and filing | frCorrections, frCorrectionOf, frRegulationsDotGovUrl |
What this lets you build: comment-deadline monitoring that does not need a human reading the FR. A regulatory affairs product filters documentType=proposed with frCommentsCloseOn inside a chosen window, groups by frDocketIds, and emails the team a queue with a direct frRegulationsDotGovUrl for each item. One feature, four fields.
frEffectiveOn feeds a different surface: a compliance calendar that shows when obligations actually start rather than when the rule was published. Those two dates are often months apart, and confusing them is an incident.
frCorrections and frCorrectionOf catch the agency fix. A monitor without them shows the uncorrected text and never mentions the correction exists. The corpus behind this block is Federal Register agency rules, final and proposed, 1994 to present, 196,000+ sections. The federal_register board on GET /boards declares a daily cadence.
Agency and executive: 9 fields
| Group | Fields |
|---|---|
| Who issued it | agencies, agencySlugs, issuingAgency |
| Presidential documents | president, signingDate, rescindedOn |
| What kind of document | documentNumber, documentSubtype, documentTypeLabel |
What this lets you build: an agency-scoped feed, and an executive order status page. agencySlugs makes the first one real, because agency names are printed inconsistently and slugs aren't. Filter on the slug, render the name.
rescindedOn and president give you the executive order surface people want: every EO signed by a given president, with the rescinded ones marked rather than deleted. That corpus runs 2015 to present, 3,600+ sections, refreshed daily.
documentSubtype and documentTypeLabel are a small lesson in schema honesty. One is for your code and one is for your UI, and merging them forces every consumer to display a slug or maintain a display map.
Corpus-specific odds and ends
The rest exist because one corpus needed them and nothing else does.
| Corpus | Fields | Why |
|---|---|---|
| Court rules | ruleSet, ruleSetCode, committeeNote | A rule belongs to a named set, and the committee note is a distinct authority that must not be blended into the rule text |
| Agency guidance | caseName, settlementAmount, requesters, program, audience, topics | An HHS OCR resolution agreement has a settlement amount, a CFTC no-action letter has requesters, and guidance has an intended audience |
| Everything | popularName, licenseNote, languageCode, wordCount, excerpt, relevanceScore, versionId, datesText, action, abstract, sourceNote, state, corpusType, source, year | Cross-cutting utility |
topics and audience answer a question statutes never raise: who was this written for. A compliance officer filtering OCC Bulletins wants the ones addressed to banks, not to examiners, and that distinction is printed on the document.
languageCode exists for one reason. The API reference says 86 percent of Puerto Rico's insurance bulletins are in Spanish (es), and Puerto Rico is the largest jurisdiction in that corpus at 1,641 sections. A row that doesn't declare its language will get fed to an English-only pipeline and quietly produce nonsense.
Most of these are null, and that is the correct design
Any given row uses a fraction of the 128. A state constitution has no frCommentsCloseOn, a Federal Register proposed rule has no committeeNote, an executive order has no chapter. That isn't a data gap. US primary law is about a dozen document types, and a superset with a documented per-corpus population is the honest way to model that in one object. The tier-by-tier version of the argument, and the three API behaviors that make it testable, are in what a legal data API should guarantee.
The wrong fix is inventing values so the shape looks full. A currencyYear derived from your ingest date rather than the publisher's statement is worse than a null, because null is checkable and a plausible wrong year isn't.
Pruning with fields, worked
A 148-field object is right for a detail view and wasteful for a list. The fields parameter cuts it down. Before, a default POST /us/statutes/search:
{
"query": "notice requirements for policy cancellation",
"corpusType": "STATE_AGENCY_GUIDANCE",
"limit": 50
}
Fifty rows, each carrying the full object: 50 x 148, or 7,400 field slots on the wire, of which the list view paints four. After, pruned:
{
"query": "notice requirements for policy cancellation",
"corpusType": "STATE_AGENCY_GUIDANCE",
"limit": 50,
"fields": ["state", "issueDate", "sectionTitle", "excerpt"]
}
Each row now carries six: the four you named plus actId and citation. That is 300 field slots instead of 7,400, roughly a 25x cut in fields on the wire for a list that looks identical to the user.
Two behaviors make this safe to depend on: actId and citation come back whether you named them or not, and an unknown field name such as sectionTtile is rejected with 422, in the shape the error reference documents, rather than dropped quietly while your UI renders a blank column. Both are part of the enforceable schema contract rather than conveniences.
Here is a real pruned response from 12 October 2026 (limit set to 1, with the four fields above):
{
"results": [
{
"actId": "MD_INS_B_06-22",
"citation": "MD Insurance Bulletin 06-22",
"state": "md",
"sectionTitle": "HB 570 - Insurance - Notice - Cancellation, Nonrenewal, and Premiums",
"issueDate": "2006-10-13",
"excerpt": "Notice of Cancellation or Nonrenewal of a commercial insurance policy must be sent at least 45 days in advance..."
}
],
"count": 1,
"creditsConsumed": 4
}
The envelope also carries hasMore, matchQuality and other fields, left out here. Then call GET /us/statutes/section/{actId} for the full object when a user opens a row. The pattern is wide on detail, narrow on lists, and you page the list under the pagination rules.
The check to run against any legal data vendor
Ask for one raw JSON response body from a real query, not a docs page and not a schema diagram. Count the fields, then check whether that body can tell you where exactly the text came from inside the source document, what it is current through in the publisher's own words, when it was last amended and on what credit, what the provision references and what references it, and where it went if it moved. Each of those maps to one of the families above, and a "no" on any of them is work that lands on you.
A vendor that answers all of them in one response body is selling infrastructure. One that answers two is selling a text feed, which is fine if a text feed is what you need and expensive if you find out after shipping. The longer questionnaire, including the paging and error-behavior tests, is in the vendor questions in the schema contract post.
One more check costs nothing: ask whether an unknown filter value returns an error or an empty result set. Silent empty results are the worst failure mode here, because a typo and a real zero-result query look identical, and you will trust the wrong one.
FAQ
How many fields does a legal API response actually need?
Far fewer than 148 for a reader view, and most of them for a product with opinions about the data. The number matters less than the coverage. Identity, hierarchy, provenance, currency, amendment history, and relationships are the six families a real product will need, and a response missing any of them pushes that work onto you.
What are sourceCharStart and sourceCharEnd for?
Where populated, they mark where a section's text begins and ends in the source document, for reconciling our extraction against the original PDF. A URL tells you which document, and the offsets tell you where in it. sourcePageStart and sourcePageEnd do the same job in page units, and the API reference documents the page fields as 100 percent populated on the Federal Rules. They are null on many rows, so check the corpus you care about.
Can I query what a statute said on a specific past date?
Yes, with limits. A citation maps to the text currently in force, and asOf=YYYY-MM-DD on the section body endpoint returns an earlier text. For corpora where we hold the publisher's printed editions that is the edition governing your date. For the rest it is a reconstruction from changes we recorded, flagged by isBounded when it rests on when capture began, and it can come back unavailable for a date before capture. Amendment history and a last-amended year per section, a yearFrom/yearTo currency filter, change events captured per refresh, and per-section diffs on a watched board sit alongside it.
Why are so many fields null?
Because a field that means something for one corpus means nothing for another. A Federal Register proposed rule has a comment close date and a state constitution doesn't, so a superset schema with documented per-corpus population is more honest than forcing every corpus into a shared shape. Null is a fact, and a fabricated value to fill it would be worse.
What does the fields parameter do?
It prunes a search response to only the fields you name, which cuts a 50-row list from 7,400 field slots to about 300 when you name four. actId and citation come back regardless, because a row without an identifier can't be re-fetched and a row without a citation can't be attributed. An unknown field name returns 422 rather than being ignored.
How do I follow a statute section that was renumbered?
Read renumberedTo and transferredTo. Those two pointers carry the citation from its old number to its new one, which matters because a system keyed on the old citation can't tell a moved provision from a repealed one. The supersedes, supersededBy, and supersessionActions fields cover the cases where a provision was replaced rather than moved.
What metadata do I need to monitor rulemaking comment deadlines?
Four fields do most of the work: frCommentsCloseOn for the deadline, frDocketIds for grouping, frEffectiveOn for the compliance calendar, and frRegulationsDotGovUrl so the user can file. Add frCorrections and frCorrectionOf so an agency correction doesn't slip past your monitor.
Why does a US legal API carry a languageCode field?
The API reference says 86 percent of Puerto Rico's insurance bulletins are in Spanish, and Puerto Rico is the largest jurisdiction in that corpus at 1,641 sections. Without a language field on the row, those documents get processed by English-only tooling and produce quiet garbage.
How much amendment history coverage should I expect from a state law corpus?
Less than a vendor's headline number suggests, and the reason matters more than the number. In our 2026-08-30 census of 3,518,180 state sections, 912,388 (25.9%) carried no amendment year at all, and a missing year is often a publisher property rather than a pipeline failure (a figure from August 2026, not re-measured in October). Ask any vendor to split their coverage figure into captured-and-parsed, captured-but-unparsed, and never-captured before comparing it to anyone else's.
New legal AI guides, weekly.
Further Reading
Hybrid Search Over 20 Million Legal Passages: Why Semantic Alone Fails on Law
Read postParsing Legal Citations in Code: Bluebook Forms, State Variants, and the Ones You Must Refuse
Read postLegal Citation Resolution: Turning a Cite Into the Right Section, Every Time
Read postWhat a Legal Data API Should Guarantee: The Schema Contract
Read postFrom a State Website to an API Response: Every Layer a Legal Corpus Passes Through
Read postAmendment History and Point-in-Time Law: What a Legal API Can and Cannot Tell You
Read post
Co-Founder & CTO
Priyansh leads engineering and AI at Vaquill AI: the pipelines that pull statutes, regulations and court rules from every US jurisdiction's official publisher, and the REST API, MCP server and open dataset that serve them.