Search the text of state session laws
Find state session laws by what they SAY. Send a question in plain words, words from a title, a quoted phrase, a citation (63-3004), a code section or a bill number (S.F.No. 1552). You get the laws, best first, each with the passage of its text that matched and a snippet around your words.
Cost: 4 credits per page, each page a new search. An empty result is an answer ("nothing matches") and is charged. A request that fails validation (422) is never charged; a failure on our side (500, 503) is refunded. To read a law you found, use GET /us/session-laws/{sessionLawId} (record) or its /body (text), which are priced on their own.
What is searched. The ENACTED text: the law as it reads once the act takes effect. Language an act strikes out is not searched and never appears in a snippet, so a repealed word cannot match as if it were law. Only laws we serve with text are searched (see GET /us/statutes/coverage, sessionLaws, for what each state holds). Laws whose text we withhold are not returned, unless you send includeUnverified (default false): then a withheld law whose reason we can label may appear, each such result carrying holdingState: quarantined, textReliability and reasonCode, and it is matched by its title, code section, citation or bill number rather than by the words of its text.
How it ranks. Keyword relevance (BM25), not meaning. Words are matched as written and stemmed (licensing finds licensed), so a question has to share vocabulary with the act: teeth cleaning professional does not find an act that says dental hygienist. A law matched by its title AND its text, or by an exact part of your query, ranks above one matched a single way. Quote a phrase to require it verbatim.
What a result says about itself. matchType is exact when a quoted phrase, citation, code section or bill number you typed matched, otherwise text; matchedBy lists every way. Neither says the law is the right one: a question with no true answer still returns its closest words, and there is no "no good match" flag because keyword scores do not separate the two cases. Read the snippet.
Paging. limit is 1 to 25. offset plus limit reaches at most the 60 best matches; narrow with jurisdiction, session, series, instrumentType or the approval dates rather than paging deeper.
curl -X POST "https://api.vaquill.ai/api/v1/us/session-laws/search" \
-H "Authorization: Bearer vq_key_..." \
-H "Content-Type: application/json" \
-d '{"query": "can the sheriff pay with a debit card", "jurisdiction": "al", "limit": 5}'
const res = await fetch("https://api.vaquill.ai/api/v1/us/session-laws/search", {
method: "POST",
headers: { Authorization: "Bearer vq_key_...", "Content-Type": "application/json" },
body: JSON.stringify({ query: '"credit card or debit card"', jurisdiction: "al", limit: 5 }),
});
const { results } = await res.json();
Related. GET /us/session-laws/list filters one state's laws by session, series and date; POST /us/session-laws/batch reads up to 50 laws by id; GET /us/statutes/section/{actId}/enactments lists the acts a publisher's own tables tie to a code section.
Request
- Base URLhttps://api.vaquill.ai
- Auth
- HTTP bearer
- or API key in header X-API-Key
- TypeScriptA function with typed inputs. Its response is checked against the schema.
Headers
Optional. 16 to 255 visible ASCII characters (a UUIDv4 is ideal). A retry with the same key and the same request replays the original 2xx response for 24 hours without charging again. The same key with a different request is rejected. Scope is the API key, method, path and body. The stored response body is a query-derived cache controlled by the account's data retention setting cacheQueryDerivedData: when it is false the body is never stored and a retry answers 409 idempotency_replay_unavailable, without charging again.
Request body
Example request
{
"query": "can the sheriff pay with a debit card",
"jurisdiction": "al",
"session": "2025R",
"series": [
"general"
],
"instrumentType": [
"act",
"joint_resolution"
],
"approvedFrom": "2025-03-01",
"approvedTo": "2025-06-30",
"limit": 5,
"offset": 5,
"includeUnverified": true
}Response
The laws that matched, best first. An empty results is a charged answer.
Example response
{
"query": "can the sheriff pay with a debit card",
"parsed": {
"text": "sheriff debit card",
"phrases": [
"debit card"
],
"citationTokens": [
"63-3004"
],
"billNumbers": [
"HB 145"
]
},
"results": [
{
"sessionLawId": "SSL_AL_2025R_G_Y2025_C2025-127",
"jurisdiction": "al",
"session": "2025R",
"series": "general",
"instrumentType": "act",
"citation": "Act 2025-127",
"title": "Relating to Houston County; to authorize the sheriff to establish procedures for using a credit card.",
"approvedDate": "2025-04-15",
"enactmentOutcome": "signed",
"billNumbers": [
"AB 2801"
],
"amendedSections": [
"1950.5"
],
"matchType": "text",
"matchedBy": [
"title",
"text"
],
"passage": {
"seq": 2,
"ownStart": 8120,
"ownEnd": 11940,
"pageStart": 3,
"heading": "Section 3.",
"snippet": "…the sheriff may establish procedures for using a credit card or debit card to make purchases…",
"highlights": [
[
13,
18
],
[
58,
64
]
],
"bodyHref": "https://api.vaquill.ai/api/v1/us/session-laws/SSL_AL_2025R_G_Y2025_C2025-127/body?startChar=8120"
},
"holdingState": "quarantined",
"textReliability": "unverified",
"reasonCode": "strike_unchecked",
"href": "https://api.vaquill.ai/api/v1/us/session-laws/SSL_AL_2025R_G_Y2025_C2025-127"
}
],
"count": 5,
"limit": 5,
"hasMore": true,
"creditsConsumed": 4,
"processingTimeMs": 38.6
}Changes
No recorded changes to this operation across all 1 revision of this API.