A CFR API returns one section of the Code of Federal Regulations as structured JSON, addressed by a stable id rather than by a URL you scraped. The Vaquill AI corpus carries 219,114 CFR sections, refreshed daily, inside a federal set of 618,875 sections. The part that trips people up is not retrieval. It is the hierarchy: the CFR is scoped by part, the US Code is scoped by chapter, and an API filter that mixes them up returns nothing or gets rejected. This post walks the hierarchy, three real queries, the CFR-versus-Federal-Register split that causes most "your data is wrong" tickets, and one honest limit.
TL;DR
- The CFR's useful scoping unit is the part, not the chapter.
17 C.F.R. Part 240is the Exchange Act rules. PasstitleNumber: 17, part: "240"and you have scoped a search to exactly that body of rules. - An unpaired
chapterorpartis rejected with a 422. Part numbers repeat across titles, so the API refuses the ambiguous call instead of returning a silently wrong page. - The CFR is the codified snapshot. The Federal Register is the amendment stream. A rule can be final and legally effective while the CFR text has not caught up. Model both or you will ship a bug.
statutoryAuthoritylinks a regulation up to its enabling statute, andimplementingRegulationsruns the same link in reverse from a USC section down to the CFR parts that implement it.- Versioning is the amendment record, not a date parameter. The corpus holds one current text per citation. What you get instead is amendment history,
lastAmendedYear, a captured change log per section, and before/after diffs on a watched board. - CFR data is refreshed daily, and
GET /us/statutes/coverageis free and reports what each corpus is current through in the publisher's own words.

Which container is the CFR's practical scoping unit in this API?
This post belongs to our US primary law corpus series, which walks the corpus one source at a time.
Two posts pair directly with this one: Federal Register API: Querying 202,526 Final and Proposed Rules covers the amendment stream that the codified text lags behind, and FAR and DFARS API: Government Contract Clauses You Can Query by Number covers the Title 48 chapter split. For the state-level analogue, see State Regulations API: 1.5 Million Administrative Rules Across 52 Jurisdictions.
The hierarchy you have to model
The CFR is 50 titles. Under a title, the structure goes chapter, subchapter, part, subpart, section. Every one of those levels appears on a result, and each one answers a different question.
| Level | What it means | Example | Useful as a filter? |
|---|---|---|---|
| Title | The broad subject area | Title 17, Commodity and Securities Exchanges | Yes, titleNumber |
| Chapter | The agency that issues the rules | Chapter II, Securities and Exchange Commission | Rarely, except Title 48 |
| Subchapter | A grouping inside an agency's rules | Subchapter A | Returned, not filterable |
| Part | One coherent rule set | Part 240, Exchange Act rules | Yes, this is the one you want |
| Subpart | A block inside a part | Subpart A | Returned, not filterable |
| Section | The citable unit | 17 C.F.R. 240.10b5-1 | This is what you retrieve |
Here is the thing most developers get backwards on their first integration. In the US Code, chapter is the meaningful container: 42 U.S.C. Chapter 21 is the civil rights chapter, and USC_T42_C21_S1983 encodes it. In the CFR, chapter tells you which agency writes the rules, which you usually already know, and part is what a compliance team actually reasons about.
Nobody says "we have an obligation under 17 CFR Chapter II." They say "we have an obligation under Part 240." So the API takes both chapter and part, and which one is load-bearing depends on the corpus you are querying.
Worked query 1: scope to 17 C.F.R. Part 240
Insider trading sits in the Exchange Act rules. To search only there:
curl -X POST https://api.vaquill.ai/api/v1/us/statutes/search \
-H "Authorization: Bearer vq_key_..." \
-H "Content-Type: application/json" \
-d '{
"query": "affirmative defense trading plan adopted in good faith",
"corpusType": "CFR",
"titleNumber": 17,
"part": "240",
"limit": 10
}'
The top hit is 17 C.F.R. 240.10b5-1, whose actId is CFR_T17_P240_S240_10b5_1. Note the shape: title, part, then the section number with dots and hyphens flattened to underscores.
Do not build that id by hand. It looks derivable and mostly is for the CFR, which is exactly what makes it dangerous. Across the rest of the corpus the container segments are not recoverable from a citation, so a hand-assembled id 404s and the failure reads like a coverage gap. Take the id from the search response, and see the section id reference for why the shape is not guessable.
Every result also carries a parent object. Pass it straight back to GET /us/statutes/divisions and you get the section's siblings, which is how you walk a part without knowing its shape in advance. The browse-hierarchy recipe works a title down to its parts.
Worked query 2: scope to a whole title
Drop part and you get the title. This is the query for "what do the SEC's regulations say about X" when you do not yet know which part the answer lives in.
-d '{
"query": "material nonpublic information",
"corpusType": "CFR",
"titleNumber": 17,
"limit": 25
}'
limit maxes at 50 and offset at 70, so one ranking gives you up to 120 results. Paging is cut from a single ranking rather than re-run per page, so results never repeat or vanish between pages, and page 3 costs the same 4 credits as page 1. The pagination rules cover both ceilings.
Worked query 3: matchType=phrase for a defined term
Default search is hybrid, semantic plus keyword. That is right for a natural-language question and wrong for a defined term, where you want the literal string and nothing adjacent to it.
-d '{
"query": "qualified financial contract",
"corpusType": "CFR",
"matchType": "phrase",
"limit": 20
}'
matchType takes any (hybrid, the default), all (every query term must appear), and phrase (exact phrase). Use phrase when you are hunting a term of art across titles and semantic neighbors would bury it.
The CFR is a snapshot, the Federal Register is the stream
This is the relationship compliance engineers keep getting wrong, and it produces a specific, repeatable bug.
An agency publishes a final rule in the Federal Register. That document has an effective date. On that date the rule is law. The CFR is the codified restatement, and the codified text is updated on its own schedule, which is not the effective date.
So there is a window, sometimes days and sometimes much longer, where the rule is in force and the CFR text you are reading does not reflect it. If your compliance product answers only from CFR text, it will confidently serve superseded language during that window and give you no signal that it did.
The fix is to query both corpora and reconcile. The Federal Register corpus holds 202,526 agency rule documents from 1994 to the present, refreshed weekly, filterable by documentType set to final or proposed, by agency, and by a publishedFrom/publishedTo window. The filters and paging rules for that side are in Federal Register API: Querying 202,526 Final and Proposed Rules.
A practical pattern for a compliance check on 17 C.F.R. Part 240:
- Retrieve the CFR sections in the part.
- Search
corpusType: "FEDERAL_REGISTER"withdocumentType: "final", the issuingagency, andpublishedFromset to a few months back. - Any final rule touching that part and not yet reflected in the codified text is your pending-amendment set. Surface it next to the answer.
That third step is the one teams skip, and it is the whole difference between a tool a compliance officer trusts and one they stop opening.
What "daily refresh" and "current through" actually mean
The CFR corpus refreshes daily. That means a job pulls from the government publisher, compares against the copy we hold, and writes what moved. It does not mean the publisher regenerated everything that day.
Two separate facts, and you want both:
- Our refresh cadence is when we last looked.
GET /boardscosts nothing and returns three fields per watchable source:cadence,lastRetrievedAt, andretrievalStatus. - The publisher's own currency is what the source says it is current through. Free at
GET /us/statutes/coverage, which returns acurrencyblock quoting each corpus in the publisher's own words, plus ameasuredAttimestamp.
Compare that to the USC in the same corpus: 60,170 sections, the 2024 edition, current through 2025-01-06, checked weekly for a new edition. Codified statute moves on an annual editorial cycle. Codified regulation moves daily. Same API, very different freshness physics, and a UI that presents them identically is lying to its user.
GET /us/statutes/coverage also returns a freshness array that declares every paused corpus with its reason, in the API response itself. Where a publisher's own robots.txt opts automated access out, the corpus pauses and says so, because honoring the publisher is the only defensible option. The full breakdown lives in the coverage docs.
Following the authority chain
A regulation is only valid because a statute authorized it. Two fields carry that link, and they are the reason a regulation lookup can answer a question a plain text search cannot.
statutoryAuthority is populated on CFR sections. It parses the section's Authority note into structured citations:
"statutoryAuthority": [
{ "type": "usc", "title": 15, "section": "78o", "display": "15 U.S.C. 78o" }
]
implementingRegulations is the reverse, populated on USC sections. It is derived from every CFR section's own statutoryAuthority, so from a statute you can see which CFR parts implement it:
"implementingRegulations": [
{ "cfrTitle": 17, "part": "240", "partName": "...", "display": "17 CFR Part 240" }
]
Alongside those, crossReferencesUsc and crossReferencesCfr carry references parsed out of the running text, not the authority note. A USC reference comes back as "42:1983", and "self:<section>" marks a pointer to another section of the same title.
The difference matters. statutoryAuthority answers "what lets this agency do this." crossReferencesUsc answers "what else does this text point at." A regulatory-graph feature needs both edges, and conflating them produces a graph that looks dense and means nothing.
The versioning model, stated precisely
The corpus holds one current text per citation. The versioning layer is the amendment record rather than a date parameter, and serving arbitrary past dates is a different storage model.
Say that plainly to your users. A tool that implies historical retrieval is worse than one that states its versioning model and lets you design around it. Here is what exists instead, and for most compliance work it covers the real question.
| What you want | What to call | What you get |
|---|---|---|
| When did the publisher say this last changed? | GET /section/{actId} | amendmentHistory and lastAmendedYear from the publisher's own credit line |
| Has this moved since we last reviewed it? | GET /section/{actId}/changes (1 credit) | Every change our refreshes observed: added, amended, removed, with detectedAt |
| Only sections amended recently | yearFrom / yearTo on search | A currency filter on the last amendment year the publisher credits |
| Tell me when this changes from now on | POST /boards/watches | Change events, then before/after diff text from the watch's diff endpoint |
Three things to be careful about here.
detectedAt is when we saw it, not when it took effect. It is an upper bound on the effective date. For the publisher's own dates, read amendmentHistory. The two are complements and neither substitutes for the other.
An empty change list means "no captured change", not "never amended". Change capture started long after the corpus did, it is per-source, and events are swept at 24 months. Every response carries a coverage field saying so. Render that, do not render an empty list as "unchanged". How We Know a Law Changed: Boards, Diffs, and the False Positives Nobody Talks About goes through what the detector can and cannot see.
yearFrom/yearTo excludes sections with no amendment credit. About a fifth of sections carry none, because some publishers print none. Set either bound and those drop out. That is correct behavior and a nasty surprise if you assume the filter is only narrowing by date.
A repealed or removed section still answers. When the newest captured change is a removed, the section is gone from the corpus and section comes back null with a successful, charged response. Learning that a provision was repealed is the point, so it is not a 404.
Where the CFR sits in the wider federal set
CFR is the largest federal corpus we carry, but the compliance answer often needs its neighbors. Every token in the corpusType column is defined in the corpus types reference.
| Corpus | corpusType | Sections | Refresh |
|---|---|---|---|
| Code of Federal Regulations | CFR | 219,114 | Daily |
| Federal Register rules, 1994 to present | FEDERAL_REGISTER | 202,526 | Weekly |
| Statutes at Large, 113th to 119th Congresses | SESSION_LAW | 110,287 | Weekly |
| United States Code, 2024 edition | USC | 60,170 | Checked weekly |
| Federal agency guidance, 34 named sources | AGENCY_GUIDANCE | 21,906 | Weekly |
| Executive Orders and Presidential Documents | EXECUTIVE_ACTION | 3,788 | Daily |
Inside CFR, source splits Title 48 into the FAR (far, 5,537 sections) and the DFARS (dfars, 2,877 sections). That is a chapter split of data already in the CFR count, not extra sections. If you build for government contractors, the companion post on the FAR and DFARS API covers the clause-lookup and flow-down patterns in detail.
SESSION_LAW items are worth one caution. They carry actStatus: "enacted" and goodLawStatus: "unknown" on purpose. They are law as enacted, a historical record of what Congress passed, not a statement of what is currently in force. Do not present a session law as current law.
FAQ
Is there an official CFR API from the government?
The government publishes the CFR through eCFR and govinfo, and both offer developer access to their own copies of the data. What that does not give you is one query surface across the CFR, the US Code, the Federal Register, and 52 state jurisdictions with a single schema and a stable id per section. That join is the work a commercial API is doing.
What is the difference between the CFR and the Federal Register?
The Federal Register is the daily stream: proposed rules, final rules, notices, presidential documents. The CFR is the codified restatement of the final rules, organized by subject into 50 titles. A rule appears in the Federal Register first and is folded into the CFR afterward, so during that window the CFR text can lag a rule that is already in force.
How do I search only one CFR part?
Send corpusType: "CFR" with both titleNumber and part, for example titleNumber: 17 and part: "240". Both are required together. An unpaired part is rejected with a 422 because part numbers repeat across titles and a wrong-title answer is worse than an error.
Can I get the CFR text as it read on a past date?
Versioning here runs off the amendment record rather than a date parameter. The corpus holds one current text per citation, with no as_of parameter. You can get the publisher's amendment history and lastAmendedYear, the change events our refreshes captured for a section, and before/after diffs on a watched board, which answers "has this moved" without answering "what did it say in 2019".
How often is the CFR data updated?
Daily. GET /boards reports the cadence, lastRetrievedAt, and retrievalStatus for every watchable source, and GET /us/statutes/coverage reports what each corpus is current through in the publisher's own words. Both endpoints are free.
What is statutoryAuthority on a CFR section?
It is the structured version of the section's Authority note: the USC citations that authorize the rule, as objects with type, title, section, and a display string. On a USC section the reverse field implementingRegulations lists the CFR parts that implement it, derived from every CFR section's own authority note.
Can I build a CFR actId from a citation?
You can for the CFR, and you should not. CFR_T17_P240_S240_10b5_1 is derivable from 17 C.F.R. 240.10b5-1, but the same habit fails across the rest of the corpus where container segments do not appear in the citation, and a hand-built id 404s in a way that reads like missing coverage. Take ids from a search response, or go from a citation with /us/statutes/resolve.
How do I get alerted when a CFR section changes?
Create a watch with POST /boards/watches against the CFR board, optionally scoped to a specific actId. Change events land as your watch's refreshes observe them, and the watch's own diff endpoint returns the before and after text. GET /boards lists every watchable source for free before you subscribe.
Does the API cover state regulations too?
Yes, under corpusType: "REGULATION", roughly 1.46 million sections across 52 jurisdictions. State administrative codes are structured differently from the CFR (Maryland runs Title, Subtitle, Chapter, for instance), so the same titleNumber and chapter filters carry different meanings there. Check GET /us/statutes/divisions for a jurisdiction before assuming a shape, and see State Regulations API: 1.5 Million Administrative Rules Across 52 Jurisdictions for the per-state shapes.
Start with the free endpoints
The honest way to evaluate a primary-law dependency is to read what it declares about itself before you spend a credit. GET /us/statutes/coverage and GET /boards are both free, and between them they tell you every corpus count, every publisher currency note, every declared pause with its reason, and every source's last retrieval time.
We build Vaquill AI, the API described in this post. Scope worth knowing up front: this is US primary law, so court opinions come from a separate source. The collection layer behind it is published at open-us-law, so the sourcing is readable rather than asserted.
New legal AI guides, weekly.
Further Reading
FAR and DFARS API: Government Contract Clauses You Can Query by Number
Read postUS Tax Treaty API: Bilateral Treaties and Technical Explanations, Citable by Article
Read postExecutive Orders API: Presidential Documents, Refreshed Daily
Read postInsurance Compliance Across 50 States: Where the Rules Actually Live
Read postState Insurance Bulletins API: 49 Insurance Departments in One Query
Read postState Constitutions API: 51 Jurisdictions With Article and Section Structure
Read post
Co-Founder & CTO
Priyansh leads engineering and AI at Vaquill, from the matter workbench to drafting, document comparison, document matrix, and citation-verified research.