The internal tool nobody wants to build twice
Every company that touches contracts eventually builds a small internal app that needs a slice of legal research. Sales wants to know if a clause holds up in Texas. Compliance wants RFPs flagged against the right federal statutes before they get routed. Legal wants intake tickets auto-tagged so the queue does not turn into a slush pile by Thursday afternoon.
The classic answer is to wire it all to a human. Legal answers Slack pings, paralegals tag tickets, ops reads RFPs at 9pm. That works until volume kills it, usually in the same quarter the company grows.
The second answer, more recent, is to plug an AI legal research tool with API access into the internal app and let the tool answer the easy 60% of questions inline.
That is what this post is about. Not "what is an API," not a feature sheet, but a working pattern for pulling statute-grounded legal answers into the apps your team already uses, with one example stack (a statutes/legislation API) and a clear map of where case-law questions belong instead.
Short answer: legal research API integration to pull statutes into your app is three calls. Authenticate with a bearer token, POST /statutes/search to find the on-point section, then GET /statutes/section/{actId}/body to render the full text with its citation. Cache the repeats server-side, log every citation, and route case-law questions to a separate source. The full walkthrough, with real curl and code, is below.
TL;DR
- A statutes-grounded legal API exposes US primary law (US Code, CFR, Federal Rules, state codes from 49 states, state constitutions, state court rules, Executive Orders and Proclamations since 2015), which is enough to answer a surprising share of internal-app questions.
- Auth in the example stack is a single
Authorization: Bearer ...header, JSON request and response. The API is self-serve: sign up and current pricing shows in your dashboard. - The pattern that works inside internal apps: keep the API key server-side, cache repeat questions, log the citation each answer cites, and reserve case-law questions for the in-app workbench, which has its own US case law research.
- The public API is statutes and legislation only. Case-law search, citation resolution, and docket data are not part of any public endpoint and live in the in-app workbench.
What is the Vaquill AI public API scoped to?
Part of our MCP and developer guide series.
For related MCP / API / developer coverage, see Legal API in 2026: What It Is, What It Returns, and How to Pick One, how to pull US Code sections programmatically, legal API vs building a RAG pipeline on cost, and how to embed a legal AI chat widget in your client portal.
Three internal apps that benefit immediately
Before the code, the use cases, because the wrong starting point is "we should add legal AI somewhere." Pick a workflow that is currently bottlenecked on a human reading a statute.
Sales: "is this customer in a state where our clause Y is enforceable?" Most B2B sales orgs lose deals not because the price is wrong, but because legal goes silent for three days while a deal desk waits for a redline. If your contract has a non-compete, a class-action waiver, or an arbitration clause, enforceability varies by state in ways your AE will never memorize.
A small panel inside Salesforce that takes "clause name + customer state" and returns the relevant state statute section and a plain-English summary of the rule turns a 72-hour wait into a five-second answer. Legal still owns the final call. Sales stops blocking on it for every routine deal.
Compliance: incoming RFP pre-screening. If you respond to government or regulated-industry RFPs, the first read is mostly mechanical. Which federal statutes does this touch? Is there a HIPAA flag, a GLBA flag, an OFAC flag, a state data-residency requirement?
You can pipe each incoming RFP through an internal app that runs the relevant text against the statutes search endpoint, pulling the federal statutes implicated by the data-handling section of the RFP. It is not the final compliance review. It is the trim that gets the document into the right reviewer's inbox half a day faster.
Legal intake auto-tagging. Every in-house legal team has an intake form. The form fills up. Tickets sit until someone manually categorizes them.
An internal app that classifies each ticket against a fixed taxonomy ("employment matter, IP matter, commercial dispute, regulatory") by asking the API to identify the applicable statute family is unglamorous and reliably valuable. It also gives you clean tags to report on six months later when someone asks "what is legal spending all our cycles on."
Notice what these have in common. They are internal, the audience is your own team, and a wrong answer gets caught by a downstream human review before it hits a customer or a court.
That is the sweet spot for legal-research APIs inside line-of-business apps. The same pattern is exactly wrong for, say, a public-facing chatbot that answers "should I sue my employer."
What you can pull from the statutes API

Here is the actual surface, scoped precisely so you know what you are signing up for.
- US Code and the Code of Federal Regulations, with section-level access. Federal coverage is 707,107 sections.
- Federal Rules of Procedure: FRCP (civil), FRCrP (criminal), FRE (evidence), FRAP (appellate), and FRBP (bankruptcy).
- State statute codes from 49 states, 1.9M+ sections, each indexed by the state's official code structure. Call
GET /api/v1/statutes/statesfor live coverage andGET /api/v1/statutes/codes?state=txfor one state's codes. - The U.S. Constitution and state constitutions, plus state court rules where the state publishes them in a machine-readable form.
- Executive Orders, Presidential Proclamations, and Presidential Memos issued since 2015, refreshed daily from the Federal Register.
- A statutes search endpoint (
POST /api/v1/statutes/search) that runs hybrid retrieval over the corpora above and returns ranked, section-level hits with citations. The whole corpus is ~2.6M sections.
Three things this list is not.
It is not case-law search. If you need court opinions (federal or state), that lives in the Vaquill AI in-app workbench, which has its own US case law research across millions of US court opinions. It is not exposed as a public API endpoint.
It is not docket or filing data. Live PACER docket pulls, judgment trackers, and motion-level filings are not in the public API.
It is not raw PACER document retrieval. You will not get those bytes from a statutes API.
The list is deliberately specific because the alternative, vague "comprehensive legal data" claims, is how internal apps end up with half-broken integrations after the demo.
A statutes-first default works for most internal apps because the questions sales, compliance, and intake actually ask are statutes-shaped: "is X enforceable in state Y," "which federal act covers Z," "which subsection controls this fact pattern." Those collapse to a section pull plus a short summary.
The architecture breaks down the moment the question is interpretive: "how have the courts construed 'legitimate business interest' in the Eleventh Circuit." That is not a statutes API question. It is a case-law retrieval question, and trying to force it through the statutes layer produces confident, wrong answers.
The request shape
The whole API is JSON over HTTPS with bearer auth. The first call you make in any new integration looks exactly like this.
curl -X POST https://api.vaquill.ai/api/v1/statutes/search \
-H "Authorization: Bearer vq_key_your_key_here" \
-H "Content-Type: application/json" \
-d '{ "query": "non-compete agreement", "corpusType": "STATE", "state": "fl", "limit": 3 }'
You get back a structured data/meta envelope. No SOAP, no XML-RPC, no GraphQL warmup, no OAuth dance. A bearer token over HTTPS, JSON in, JSON out. Note the state code is lowercase two letters (fl, tx, ny).
Each result carries an actId (a structured section identifier like USC_T42_C21_S1983), a citation, a breadcrumb of the title hierarchy, and an excerpt. You never hand-build the actId. You take it from the search response and pass it to the section endpoint to fetch the full text:
curl https://api.vaquill.ai/api/v1/statutes/section/USC_T42_C21_S1983/body \
-H "Authorization: Bearer vq_key_your_key_here"
That body call returns the full provision; the metadata-only variant at /statutes/section/{actId} returns the section's identity and hierarchy without the body text. The keys are prefixed vq_key_ so a leaked one is easy to grep for in logs and revoke from the dashboard.
For the broader anatomy of "what makes a good legal API response shape," the legal API guide walks through it. This post is going to assume you are ready to write code.
A working TypeScript wrapper
Here is the entire integration layer for an internal app. One file, two functions. Drop it behind your existing service routes.
// lib/legalApi.ts
const BASE = "https://api.vaquill.ai/api/v1";
const KEY = process.env.VAQUILL_API_KEY;
if (!KEY) throw new Error("VAQUILL_API_KEY missing");
const headers = {
Authorization: `Bearer ${KEY}`,
"Content-Type": "application/json",
} as const;
type CorpusType =
| "USC"
| "CFR"
| "STATE"
| "CONSTITUTION"
| "STATE_CONSTITUTION"
| "FEDERAL_RULES"
| "STATE_RULES"
| "EXECUTIVE_ACTION";
export async function searchStatutes(opts: {
query: string;
corpusType?: CorpusType;
state?: string; // lowercase 2-letter, e.g. "fl"
limit?: number;
}) {
const res = await fetch(`${BASE}/statutes/search`, {
method: "POST",
headers,
body: JSON.stringify(opts),
});
if (!res.ok) throw new Error(`statutes/search ${res.status}`);
return res.json();
}
// actId comes from a search result (e.g. "USC_T42_C21_S1983").
// Never hand-build it. /body returns full section text.
export async function getSectionBody(actId: string) {
const res = await fetch(
`${BASE}/statutes/section/${encodeURIComponent(actId)}/body`,
{ headers },
);
if (!res.ok) throw new Error(`statutes/section/body ${res.status}`);
return res.json();
}
And the calling code, the part that actually lives inside your internal app, looks like this. Imagine an endpoint behind your Salesforce or HubSpot UI that takes a clause name and a state and surfaces the controlling statute.
// app/api/clause-check/route.ts (Next.js handler, but the shape is universal)
import { searchStatutes, getSectionBody } from "@/lib/legalApi";
export async function POST(req: Request) {
const { clause, state } = await req.json();
// 1. Pull the underlying state statutes, if there are any on point.
const statutes = await searchStatutes({
query: clause,
corpusType: "STATE",
state: state?.toLowerCase(),
limit: 3,
});
// 2. Take the top hit's actId and fetch its full text for in-panel rendering.
const top = statutes.data?.results?.[0];
const section = top ? await getSectionBody(top.actId) : null;
return Response.json({
statutes: statutes.data?.results ?? [],
citation: top?.citation,
section: section?.data,
});
}
Two calls. Less than fifty lines of code, including the wrapper. The search returns ranked hits with citations, the body call returns the full section text. Your internal UI renders them next to each other. The sales rep sees the citation, opens the section if they want, and reads the rule in context.
The thing to internalize: every field your user sees on screen has a verifiable source two clicks away. That is the property that makes an internal legal-research panel safe to ship.
Without it you are just generating confident text, which is exactly the problem that lands lawyers in front of judges for fabricated citations (more on that in how to verify AI legal citations before filing).
Patterns that actually hold up in production
A handful of patterns separate an internal legal panel that ships and stays useful from one that gets quietly turned off six weeks later.
Server-side proxy, always
Never put vq_key_... in the browser. Not in a NEXT_PUBLIC_ env var, not in a service worker, not in a "for now" dev key. Any internal app that calls the API should go: browser to your server, server to the legal API. The key lives only in your backend secrets store.
This sounds obvious until you watch a hackathon project ship a debug build with the key in the bundle. Treat the key the way you treat your Stripe secret. Same level of paranoia.
Cache the obvious repeats
Sales asks "is a class-action waiver enforceable in California" three times a week. Compliance pings the same FCRA section every other RFP. Internal apps in particular have heavy query repetition because the questions come from the same business workflows.
A simple cache on (query, state) with a 24-hour TTL drops your API spend by 30 to 70% in real installs, and improves latency for the user from sub-second to instant.
The most common cache failure I keep watching teams ship is a key that omits the state. The Salesforce panel works fine in a Texas demo, then a New York deal asks the same clause question and reads the cached Texas answer.
Include every variable that changes the response in the cache key, normalize state codes to uppercase, and lowercase the query before hashing. Redis is overkill for most internal apps; an in-process LRU with a few thousand entries does the job. Skip the cache when the user has explicitly hit a "re-run" button, so they can refresh stale answers when they need to.
Log the citation, not just the answer
Every time the API returns, log the query, the results, and the list of cited sections. Two reasons.
First, when your downstream reviewer (lawyer, compliance officer, whoever) flags a wrong answer, you need to see what the search returned, not just what your UI rendered. Second, six months in you will want to know which sections your team is hitting most often, because that tells you where to invest the next round of internal tooling.
A row per call in a Postgres table is enough. You do not need an observability platform for this.
Route case-law questions to the workbench
A real example: a customer in Florida asks whether their non-compete is enforceable. Florida codified the rule in Fla. Stat. ยง 542.335, and the statutes API will return that section cleanly.
But the interpretation of the statute, the cases that define what "reasonable time" and "legitimate business interest" mean, lives in court opinions. For that you use the Vaquill AI in-app workbench, which has its own US case law research.
The split is straightforward. The statutes API returns the section text for embedding directly in your internal tool. Interpretive, opinion-level questions go to the workbench, where the user sees the statute alongside the leading cases.
The reason to split it that way is that the freshness profiles are different. Statutes change slowly and centrally. Court opinions land every business day across dozens of jurisdictions.
Trying to keep both in one ingestion pipeline is the kind of decision teams regret. Two specialized sources, one synthesis layer, is the cleaner architecture.
What it costs
Pricing is self-serve, not negotiated. Sign up and the current rates plus your live usage show in your dashboard, with no card and no contract. Failed and not-found calls are not charged.
Live pricing is on the legal API page.
For an internal app at a 200-person company, the spend is modest once usage stabilizes. That is the number to take to your finance partner when you propose the project.
It is small enough that getting it approved is rarely the bottleneck. Getting an internal stakeholder to actually own the panel after it ships is.
The other quiet failure mode worth flagging: how reviewers handle low-confidence answers. The panel returns a citation, the sales rep treats it as gospel, and there is no signal in the UI that says "this was a single hit with a mid-tier rerank score."
Surface the confidence signal explicitly. Ours: green if the top hit is a strong rerank above a tuned threshold, yellow if it is below that but above the floor, red if the result set is empty or all results sit under the floor. Yellow and red route to a named human inside the workflow tool.
A panel that returns the same confident UI for "found the controlling subsection" and "found something vaguely on-topic" is the panel that quietly trains people to stop checking.
Where this approach falls short
Three places I would not point a junior engineer at this without flagging the limits.
Active litigation strategy. If a partner needs to brief a novel issue with adversarial cases and citation-level treatment analysis, this is not the right tool. They need a research workbench with case-law search, citation networks, and the ability to drill into treatment history.
That is a different surface (an in-app workbench layer handles case-law research, but it is not exposed as a public API). The API itself is a developer tool for embedding sourced statutory answers into other software.
Anything safety-critical without human review. Internal app does not mean "no review." It means "the review happens inside the company."
Build the panel so that a thin or empty result set routes to a human, every time. If the API returns zero or one hits on a question your team thinks is well-trodden, treat it as low-confidence and surface it differently.
Jurisdictions outside the US. The public API is US-only. If your internal app needs UK, EU, or Australian primary law, you need a different provider for those layers.
FAQ
How do I integrate a legal research API into my internal app?
Three steps. Store the API key in your backend secrets, never the browser. Call POST /statutes/search with the user's query and a corpus filter to get ranked sections with citations. Then call GET /statutes/section/{actId}/body with the top hit's actId to render the full text. Cache by (query, state) and log every citation.
Can I pull statutes into my app with an API?
Yes. A statutes API returns US primary law (US Code, CFR, Federal Rules, state codes, constitutions, Executive Orders) as structured JSON with citations. You search by natural-language query, get back section-level hits, and fetch the full text of any section by its actId. The example in this post does it in under fifty lines of TypeScript.
Is there a legal data API for case law too? Statutes and case law are separate layers. The Vaquill AI public API is statutes-only. Court opinions live in the Vaquill AI in-app workbench, which has its own US case law research across millions of US court opinions, but case law is not exposed as a public API endpoint.
How much does legal data API integration cost? Pricing is self-serve. Sign up and the current rates plus your usage show in your dashboard, with no card and no sales call. Failed and not-found calls are not charged, and a typical internal app at a 200-person company keeps spend modest once usage stabilizes.
How do I authenticate with the API?
A single header: Authorization: Bearer vq_key_.... JSON in, JSON out, over HTTPS. No OAuth flow. Keep the vq_key_ token server-side and proxy every call through your own backend so it never reaches the browser.
What format are the statute results in?
Each search result carries an actId (a structured identifier like USC_T42_C21_S1983), a citation, a breadcrumb of the title hierarchy, and an excerpt. You pass the actId, not a hand-built citation, to the section endpoint to fetch full text.
How do I keep cached legal answers from going stale? Include every variable that changes the answer in the cache key (query plus state, normalized), set a 24-hour TTL, and add a "re-run" button that skips the cache. Statutes change slowly, so a day-long TTL is safe. Case-law answers change faster, so cache those for shorter or not at all.
Where to go from here
If your weekend project for this quarter is a Salesforce panel that surfaces controlling statutes in your customer's state, or an intake bot that routes incoming legal requests by statute family, or a compliance trim that flags RFPs against federal acts, the pattern in this post is the one I would start with. Search plus section-body, server-side wrapper, cache the repeats, log the citations, fall back to a human on anything thin.
Want to try it on your own app? The Vaquill AI legal API is self-serve: sign up at app.vaquill.ai, or email contact@vaquill.ai. No sales call required. Generate a key, run the curl above, and you have a statute-grounded answer in your internal tool by the end of the afternoon.
New legal AI guides, weekly.
Further Reading
Court Records API vs Court Data API: Which One Your App Actually Needs
Read postHow to Embed a Legal AI Chat Widget in Your Client Portal or Intranet
Read postUS Statutes API: The 2026 Guide to USC, CFR, and State Code Access
Read postLegal Research API Pricing for Internal Knowledge Management
Read postLegal API in 2026: What It Is, What It Returns, and How to Pick One
Read postUSC API: How to Pull US Code Sections Programmatically
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.