US Session Laws

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.

post/api/v1/us/session-laws/search

Request

Headers

Idempotency-Keystring nullable

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.

Example:3f9c2a1e-7b44-4d0a-9c1e-5a6b7c8d9e0f

Request body

querystring required

What to look for: a question in plain words (can a sheriff pay with a debit card), words from a title, a quoted phrase ("credit card or debit card"), a citation (63-3004), a code section or a bill number (S.F.No. 1552). Quoted parts must appear verbatim; everything else is matched on its words, stemmed, so licensing finds licensed. Words are matched as the legislature wrote them: teeth cleaning professional does not find an act that says dental hygienist. 2 to 300 characters.

jurisdiction'al' | 'ak' | 'as' | 'az' | 'ar' | 'ca' | 'co' | 'ct' | 'de' | 'dc' | 'fl' | 'ga' | 'gu' | 'hi' | 'id' | 'il' | 'in' | 'ia' | 'ks' | 'ky' | 'la' | 'me' | 'md' | 'ma' | 'mi' | 'mn' | 'ms' | 'mo' | 'mt' | 'ne' | 'nv' | 'nh' | 'nj' | 'nm' | 'ny' | 'nc' | 'nd' | 'mp' | 'oh' | 'ok' | 'or' | 'pa' | 'pr' | 'ri' | 'sc' | 'sd' | 'tn' | 'tx' | 'ut' | 'vt' | 'vi' | 'va' | 'wa' | 'wv' | 'wi' | 'wy' nullable

Limit to one state, dc or pr. Two-letter code, case-insensitive. Omit to search every jurisdiction we hold. federal and an unknown code are a 422, never charged.

sessionstring nullable

Limit to one session, by the code session.code reports (2025R, 2025S1). Case-sensitive. Matches the act's own session, so it narrows the TITLE, citation and bill signals; the passage text of an act carries its session year and type but not the code.

seriesstring[] nullable

Limit to these numbering series, one or more (they combine with OR). One of general, public, public_act, special_act, private_and_special, act, acts, law, local, municipal, appropriation, resolve, resolves, resolution, resolution_chapter, joint_resolution, concurrent_resolution, memorial, initiated_bill, constitutional_amendment, private, constitutional_resolution, competing_measure_resolution, resolution_act. Any other value is a 422, never charged.

instrumentTypestring[] nullable

Limit to these kinds of measure, one or more (OR). One of act, joint_resolution, concurrent_resolution, resolution, resolve, memorial, other. Any other value is a 422, never charged.

approvedFromstring date nullable

Only laws approved on or after this date, YYYY-MM-DD, inclusive; a real calendar date (2025-02-30 is a 422). A law with no printed approval date never matches.

approvedTostring date nullable

Only laws approved on or before this date, YYYY-MM-DD, inclusive. An end before approvedFrom is a 422, never charged.

limitinteger

Laws per page, 1 to 25. A page costs the same however many laws it holds, so a larger limit is cheaper per law.

offsetinteger

Laws to skip, for the next page: offset plus limit can reach at most the 60 best matches. Each page is a new search and is charged. Deeper than 60 is a 422, never charged: narrow the search with a filter instead.

includeUnverifiedboolean

Also search laws we hold but do not serve (holdingState: quarantined). Default false: such laws are never returned and nothing else changes. With true a held-back law whose reason we can label may appear, and every such result carries holdingState, textReliability (unverified or known_issue) and reasonCode; its text MAY show deleted or vetoed law as if enacted. Served laws are returned as usual, without these fields. A law whose licence bars use, or whose text failed our own validation, is never returned. A held-back law is matched by its title, code section, citation or bill number, not by the words of its text. Priced as any search page.

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.

querystring required

The query as read, whitespace collapsed.

countinteger

Laws on this page.

offsetinteger

The offset this page was read from.

limitinteger

The limit this page was read with.

hasMoreboolean

True when more laws follow: call again with offset raised by limit (within the 60 best).

creditsConsumedinteger

Credits actually charged for this call, never the list price. 0 when the call was refunded.

processingTimeMsnumber

Server-side time for this request in milliseconds, excluding network transit. Not billed on.

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.