
Short answer: "compliance API" means two different things. One is an API that checks something for you: it screens a name against a sanctions list or verifies a customer's identity. The other is an API that supplies the regulatory text so your own compliance logic can run on it: the CFR part, the agency guidance, the state regulation, each with a stable id, a source link and a change history. If you want the first kind, the vendors in the next section are your starting point. This guide is about the second kind, which is the one you need when your product has to show which rule it applied and whether that rule was current.
TL;DR
- Screening and KYC APIs answer "is this party or transaction a problem?" Regulatory data APIs answer "what does the rule say, and has it changed?" They are separate purchases.
- Real compliance logic needs three things from rule text: a citation you can resolve to one provision, the currency of the text you are holding, and a way to find out when it changes.
- The eCFR and the Federal Register are free and good, but they publish documents. Turning an obligation into a stable record with an amendment trail is work you do on top.
- A hosted regulatory data API gives you that record by citation. Check what it says about cadence and last retrieval for each source before you rely on an alert.
- For state rules and agency guidance there is no single federal feed, so the question of coverage per source matters more than the question of format.
One team wants an API that blocks payments to sanctioned parties. Another wants one that tells their app what the beneficial ownership rule requires. Are they shopping for the same kind of product?
Part of our MCP and developer guide series.
The two meanings of "compliance API"
Search for the term and you get a mix of products that have little in common. Sort them by the question they answer.
| Kind | Question it answers | Typical inputs | Examples |
|---|---|---|---|
| Check API | Is this person, company or payment a problem? | A name, an ID document, a transaction | Sanctions screening, identity verification, AML monitoring |
| Regulatory data API | What does the rule say, and is my copy current? | A citation, a topic, a date | CFR parts, agency guidance, state regulations |
On the check side, two sources are worth knowing because they publish their own terms. OFAC's Sanctions List Service offers the SDN List and the non-SDN consolidated lists for download in several formats, plus a search application that uses fuzzy matching on names. OpenSanctions publishes sanctions and PEP data and offers a hosted screening API billed by the query; its data is licensed under Creative Commons Attribution NonCommercial for free use, and commercial use goes through a separate licence. Both descriptions come from the publishers' own pages, read when this post was written, so confirm the current terms before you build on either.
The rest of this guide covers the second kind.
What a compliance product needs from rule text
A compliance feature usually reduces to: given a situation, find the obligation, apply it, and be able to explain why. Three data problems sit under that.
Mapping an obligation to its governing citation. "Verify the owners of a business customer" is not a lookup key. 31 C.F.R. § 1010.230 is. Your system needs a way to go from the citation a compliance officer writes to one record, every time, without hand-building an id.
Knowing the currency of the text. The regulation you read last quarter may have been amended. You need to know what version you hold, where it came from, and when it was last refreshed.
Keeping up with change. Rules get amended through the Federal Register and then rolled into the CFR. A product that cites a stale rule is worse than one that cites nothing, because it looks authoritative.
Where the rule text lives
| Source | What it gives you | Auth | What you still build |
|---|---|---|---|
| eCFR (ecfr.gov) | The current CFR, updated daily, with a versioner API that lists a section's versions | None | Citation resolution, storage, change alerts |
| Federal Register API | Final and proposed rules, notices, with metadata | None (the docs say no keys are needed) | Linking each document to the CFR section it amended |
| Agency sites | Guidance, bulletins, FAQs | None | A scraper per agency, and a change detector |
| State regulation sites | State administrative codes | None | One pipeline per state |
| A hosted regulatory data API | Sections by citation as JSON, with change history | API key | Your own compliance logic |
One point on the eCFR matters for compliance work. The Office of the Federal Register, on the eCFR page titled "What is the eCFR, and what is the legal status of this publication?", describes it as an editorial compilation of CFR material and amendments published in the daily Federal Register, maintained as an informational resource, with the stated goal of eventually having it recognized as an official publication. If your product cites it, record that fact next to the text. We cover the free federal feeds in detail in the CFR API guide and the Federal Register API guide.
A worked example: 31 C.F.R. § 1010.230
Take a real obligation. FinCEN's customer due diligence rule requires covered financial institutions to identify and verify the beneficial owners of legal entity customers. The provision is 31 C.F.R. § 1010.230. Here is what a compliance product can pull for it from the Vaquill AI API. Paths and field names in this post come from the live OpenAPI spec at api.vaquill.ai/external/openapi.json, and the output below was captured by running these calls on 2026-10-04. Paths written without a host, such as /us/statutes/coverage or /boards, are relative to https://api.vaquill.ai/api/v1. Later responses may differ as the sources refresh.
import os
import requests
API = "https://api.vaquill.ai/api/v1/us/statutes"
H = {"Authorization": f"Bearer {os.environ['VAQUILL_API_KEY']}"}
# 1. Citation in, stable id out.
r = requests.get(f"{API}/resolve", headers=H,
params={"cite": "31 CFR 1010.230"}).json()
sec = r["section"]
act_id = sec["actId"] # CFR_T31_P1010_S1010_230
# 2. The text itself, with the official source link.
body = requests.get(f"{API}/section/{act_id}/body", headers=H,
params={"format": "plain"}).json()
print(body["sourceUrl"]) # https://www.ecfr.gov/current/title-31/part-1010/section-1010.230
print(body["plain"][:400])
# 3. Fields that tie the rule to its neighbours and its history.
print(sec["crossReferencesCfr"]) # ['1010.605', '1010.620', '1020.100', ...]
print(sec["statutoryAuthority"]) # the U.S.C. sections it rests on
print(sec["federalRegisterCitations"]) # ['81 FR 29451', '82 FR 45183']
print(sec["amendmentYears"]) # [2017, 2016]
The first line of the returned text reads: "(a) In general. Covered financial institutions are required to establish and maintain written procedures that are reasonably designed to identify and verify beneficial owners of legal entity customers and to include such procedures in their anti-money laundering compliance program required under 31 U.S.C. 5318(h) and its implementing regulations."
Here is the shape of the section object from step 1, trimmed to the fields used above (lists shortened with ...):
{
"resolved": true,
"inputCitation": "31 CFR 1010.230",
"section": {
"actId": "CFR_T31_P1010_S1010_230",
"citation": "31 C.F.R. § 1010.230 (2026)",
"corpusType": "CFR",
"partName": "GENERAL PROVISIONS",
"actStatus": "in_force",
"crossReferencesCfr": ["1010.605", "1010.620", "1020.100", "1020.220", "..."],
"crossReferencesUsc": ["12:1467a", "12:1841", "31:5318"],
"statutoryAuthority": [{"type": "usc", "title": 12, "section": "1829b", "display": "12 U.S.C. 1829b"}, "..."],
"federalRegisterCitations": ["81 FR 29451", "82 FR 45183"],
"amendmentYears": [2017, 2016],
"sourceUrl": "https://www.ecfr.gov/current/title-31/part-1010/section-1010.230"
}
}
Look at what else came back. The record names the other CFR sections it points to, the statute it rests on (31 U.S.C. 5318), and the two Federal Register documents behind it. You can cross-check that history against the eCFR versioner, which lists this section's versions on 2016-12-23 and 2017-09-28. The two sources agree, and your product can say so.
Store the actId, the sourceUrl, the date you fetched the text, and a hash of the text. When a reviewer asks why the system gave an answer, that row is the evidence. The same lookup works when you only have free text: a search call finds the section and returns the same fields:
curl -s -X POST "https://api.vaquill.ai/api/v1/us/statutes/search" \
-H "Authorization: Bearer $VAQUILL_API_KEY" -H "Content-Type: application/json" \
-d '{"query": "beneficial owners of legal entity customers", "corpusType": "CFR", "titleNumber": 31, "limit": 3}'
For this query the top hit is CFR_T31_P1010_S1010_230. The citation resolution guide covers how citations map to ids.
A short history of two beneficial ownership rules
The worked example above is a good place to see why dates matter, because the same subject, who really owns a company, has produced two rules with very different lives.
The first is the customer due diligence rule. FinCEN published it in the Federal Register on May 11, 2016. It was effective July 11, 2016, and it added "a new requirement to identify and verify the identity of beneficial owners of legal entity customers." The Federal Register notice also says covered financial institutions "must comply with these rules by May 11, 2018." (Customer Due Diligence Requirements for Financial Institutions, 81 FR 29398.) Notice that one rule has an effective date and a separate compliance date, two years apart. A tool that tracked "the date the rule changed" would have had to pick one.
The second is the beneficial ownership reporting rule, which asked companies themselves to file ownership reports with FinCEN. Its path was bumpier. On March 1, 2024 a federal district court in Alabama entered a judgment in National Small Business United v. Yellen, and FinCEN posted a litigation alert about it. On March 26, 2025 FinCEN published an interim final rule that exempted U.S.-formed companies and their U.S. owners from reporting. On August 11, 2026 it issued a final rule making those exemptions permanent, effective August 14, 2026. (FinCEN, Beneficial Ownership Information Reporting.)
The most useful sentence on that page is a warning from the agency to its own readers: "Some information on this website may be outdated. Please disregard any guidance stating that: U.S. companies or their beneficial owners must report BOI." If a compliance product had cached the 2024 version of this requirement, its answer would have been wrong while looking perfectly sourced.
Developers watched the whiplash in real time. In December 2024 one Hacker News commenter recalled submitting the headline "FinCEN Says CTA Reports Are Voluntary (For Now) Following Court Decision" about two weeks earlier, then thanked another user for a "last-minute update" about a "sudden shift." (miles, Hacker News, December 2024.) That is the job a change feed has: tell you when the ground moved, with the publisher's dates attached, so a person can decide what it means for a client.
Keeping up with change
Now the harder half. Here is a section that moved. 31 C.F.R. § 1010.380, the beneficial ownership reporting provision, carries amendment years 2022, 2023, 2024, 2025 and 2026, and six Federal Register citations in its federalRegisterCitations field: 87 FR 59591, 88 FR 76997, 88 FR 83504, 89 FR 83783, 90 FR 13697 and 91 FR 52528. One call tells you what the refreshes have observed:
curl -s "https://api.vaquill.ai/api/v1/us/statutes/section/CFR_T31_P1010_S1010_380/changes" \
-H "Authorization: Bearer $VAQUILL_API_KEY"
The response lists change events with changeKind (added, amended or removed), detectedAt and a hasDiff flag. For this section it returns one amended event:
{
"actId": "CFR_T31_P1010_S1010_380",
"changes": [
{
"id": 19888,
"changeKind": "amended",
"detectedAt": "2026-08-21T03:23:54Z",
"displayCitation": "31 C.F.R. § 1010.380 (2026)",
"hasDiff": true,
"corpusType": "cfr"
}
],
"hasMore": false,
"cursor": 19888,
"observedFrom": "2026-08-21T03:23:54Z",
"coverage": "Observed changes only: ... an empty list means no captured change rather than never amended."
}
Note observedFrom: it is the earliest change captured for this section, which tells you how far back the trail can be trusted. Two cautions come straight from the spec, and both matter for a compliance product.
detectedAtis when the refresh saw the change. It is an upper bound on the effective date. Do not show it to a user as the date the law changed. The publisher's own dates are in the section'samendmentHistoryand, for the CFR, insourceChangedOnon change events.- An empty history means no captured change. It does not mean the section was never amended. Capture started at a point in time, per source, and each response carries a
coveragenote saying so. Show that note instead of rendering "unchanged".
To get told rather than poll, subscribe to a board. A board is a tracked source, such as the eCFR or the Federal Register. You can narrow a watch to one part, one section or one named source:
curl -s -X POST "https://api.vaquill.ai/api/v1/watches" \
-H "Authorization: Bearer $VAQUILL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"corpusType": "cfr",
"channel": "webhook",
"webhookUrl": "https://example.com/hooks/cfr",
"webhookSecret": "choose-a-long-random-string",
"scope": {"title": "31", "part": "1010"}
}'
The create call returns the watch with its id, which is the {id} in the watch routes below. Deliveries arrive as board.updated events. Each one carries a deliveryId for de-duplication and a changes[] list whose ids you can pass to GET /watches/{id}/changes/{changeId}/diff for the before and after text. When you set a webhookSecret, every delivery is signed in an X-Vaquill-Signature header (HMAC-SHA256 over the raw body bytes), so verify it before you act. Channels are webhook, email or both. The body also carries sectionsAdded, sectionsAmended and sectionsRemoved counts narrowed to your scope, which it echoes back, and a changesOverflowCount when a refresh produced more changes than fit in one delivery. Read the sections* counters, since the rows* counters describe the whole board's storage run. The law change webhooks guide walks through the receiver.
One habit saves you from a bad assumption. Cadence is set per source, not per account. GET /boards needs an API key but costs no credits, and lists each board with its cadence, lastRetrievedAt and retrievalStatus. Read lastRetrievedAt before you treat a quiet week as a week with no changes, and check retrievalStatus the same way. The board listing also says whether a source carries the publisher's own change date (publishesSourceChangedOn), which is true for the CFR board. This is the CFR entry from GET /boards?corpusType=cfr, trimmed:
{
"corpusType": "cfr",
"label": "eCFR",
"cadence": "daily",
"lastRetrievedAt": "2026-10-04T03:00:12Z",
"retrievalStatus": "current",
"publishesSourceChangedOn": true,
"changeSignal": "continuous"
}
Point-in-time reads
Auditors ask what the rule said on a given day. The body endpoint takes an asOf date (YYYY-MM-DD) and returns the text as it stood then. Do not take the answer on faith. The response includes an asOf block that names the engine that answered, the source of the text, an isBounded flag, and observedFrom, the earliest change captured. A minimal call looks like GET /us/statutes/section/{actId}/body?asOf=2020-01-01&format=plain. For 31 C.F.R. § 1010.230 it returned this block:
"asOf": {
"requested": "2020-01-01",
"engine": "observed_change",
"source": "live",
"existed": true,
"isBounded": true,
"observedFrom": null
}
Here source: "live" means no change was captured after that date, so today's text stood then. The coverage note in the same response says how far back capture reaches. Record the whole block next to the text you cite. For the CFR, the annual editions are a separate route, covered in CFR annual editions and point-in-time reads, and the general pattern is in amendment history and point-in-time law.
Beyond the federal CFR
Federal regulations are the easy part. Compliance work also touches state administrative codes, agency guidance and manuals. The search endpoint reaches these through separate corpusType values (matched case-insensitively, so CFR and cfr both work; watches take the board's lowercase name): REGULATION for state administrative regulations (paired with state), AGENCY_GUIDANCE for sub-regulatory federal guidance, scoped by source (for example the FinCEN, IRS or OCC series), and STATE_AGENCY_GUIDANCE for state insurance bulletins. Guidance carries less legal weight than a regulation, and your product should label it that way. The federal agency guidance API guide and the state regulations API guide cover each. Call /us/statutes/coverage for the live list of what is held per jurisdiction and corpus before you scope a build.
Which approach fits
The eCFR and the Federal Register are the primary sources, and both are free. A hosted layer adds what a compliance product needs on top of them: citation resolution, a stable id per provision, amendment trails, and watches across federal, state and guidance sources in one schema. We build the Vaquill AI API for that.
This guide is part of US Law Data: The Complete Guide, a map of where US law comes from and how to use it.
FAQ
What is a compliance API? The term covers two kinds of product. One checks a party or transaction, for example sanctions screening or identity verification. The other supplies the regulatory text, such as CFR parts and agency guidance, so your own software can apply the rules and cite them.
What is a regulatory compliance API? Usually it means the second kind: an API that returns regulations by citation as structured data. It gives your compliance product the rule text, a stable id, a source link and a history of changes, so each answer can point to the provision it relied on.
Where can I get regulatory data for free? The eCFR provides the current CFR with a versioner API, and the Federal Register API provides rules and notices; the Federal Register documentation says no API keys are required. You still need to build citation resolution, storage and change alerts yourself.
How do I know a regulation changed?
Poll a section's /changes history, or subscribe to a board with a watch and receive a webhook or email. Remember that detectedAt is when the refresh saw the change, not the effective date, and that cadence differs by source. Check lastRetrievedAt on the board first.
Can I get the text of a regulation as of a past date?
Yes, with the asOf parameter on the body endpoint. Read the asOf block in the response, which tells you the engine, the source and whether the answer is bounded by when capture began, before you cite the text in a filing or audit.
Does a compliance API cover state regulations?
Coverage is specific to each state and each code, because there is no single federal feed for state regulations. Use the REGULATION corpus with a state filter, and call /us/statutes/coverage to see what is held for the states you need before you build.
Is the eCFR an official legal source? The Office of the Federal Register describes the eCFR as an editorial compilation that is maintained as an informational resource. Record the version and date of the text you cite, and check the official publication when a filing depends on it.
What should I store to show my work?
Keep the citation, the stable actId, the sourceUrl, the fetch date, a hash of the text and any asOf block. With those items you can reproduce what the product saw, and show it to a reviewer.
New legal AI guides, weekly.
Further Reading
Regulations.gov API: Dockets, Documents and Comments Explained
Read postOpen States API Guide: v3 Endpoints, Keys, Bulk Data, and Licensing
Read postLegiScan API Guide: Bills, Votes, Datasets, and Joining Them to Enacted Law
Read postCongress.gov API Guide: What It Covers and What It Doesn't
Read postUSLM vs Akoma Ntoso: How to Read Legislative XML
Read postThe Long-Tail Regulators: CFTC, FCC, FERC, DOE, and CPSC Guidance in One API
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.