POST /us/statutes/search accepts a terms-and-connectors expression when you send matchType: "boolean".
It is the syntax used by the major legal research services: AND, OR, NOT, same-sentence and same-paragraph connectors, numeric proximity, wildcards, exact phrases and grouping.
- Every result satisfies the expression, judged over the section’s full text, not over one excerpt or one passage.
- Results are ranked by relevance among the matches. The expression decides which sections qualify, and relevance decides their order.
- Nothing is silently loosened or misread. A malformed expression, an operator we do not support, or an out-of-bounds value is a
422that names the problem and its character position, and it is not charged.
When to use Boolean instead of any
Boolean mode is a filter you control.
If you want the API to infer intent from a question, stay on
any.
If you need to say exactly which sections qualify, and to be told when your expression cannot be read, use boolean.
Quick start
parsedQuery:
state, corpusType, code, titleNumber, chapter, part, yearFrom, yearTo, excludeRepealed and the rest) and includeBody work exactly as they do for any search.
The scope filters narrow the corpus first, and the expression is judged inside that scope.
Operators
Word operators are UPPERCASE. Lowercaseand, or and not are ordinary words.
Some details that matter in practice:
- Distance counts word positions.
/1means adjacent, andnotice /3 terminationmatches “notice of the termination” (three positions apart) but/2does not. atleastN( )andatmN( )take one term, phrase or wildcard:atleast3("trust fund"),atleast2(retaliat*).- Matching is on whole words, case-insensitively, with no stemming and no synonyms.
depositdoes not matchdeposits, so writedeposit*ordeposit OR depositswhen you mean both.actnever matchesfact. - Punctuation inside a word splits it.
§ 1983is the phrasesection 1983, andrule 10b-5is the phraserule 10b 5. - A hyphenated word on its own also matches its joined form.
non-competeis read as"non compete" OR noncompete, andat-willas"at will" OR atwill. - A slash between two words is text, not an operator.
and/oris the phraseand or, and24/7is24 7. Anything else containing/,~or^that is not a known operator is refused, never searched as words.
Precedence
Without parentheses, operators bind in this order, tightest first:OR(andXOR)/Nand+N/sand+s/pand+pANDNOT
+ form binds before the unordered / form.
Otherwise operators group left to right.
This is the convention of legal research services, not textbook Boolean, where AND binds tighter than OR.
parsedQuery parenthesizes every group whose reading could be in doubt, so you can read back exactly how your expression was grouped, and queryWarnings flags AND and OR mixed without parentheses.
When in doubt, add parentheses.
They never change a correct expression, and
parsedQuery drops the ones that are redundant.
Each side of a proximity connector (/N, /s, /p and their + forms) must be a term, phrase, wildcard, fuzzy term, an OR group of those, or another proximity expression.
AND, NOT and the counting functions cannot sit inside one: (a AND b) /5 c is a 422.
Also accepted
You can paste a search written in another service’s syntax. Each spelling below is read as the operator shown, andparsedQuery echoes the canonical form.
A
- before a word is NOT, so penalty -6672 excludes 6672 rather than searching for it.
A ! before a word is refused: one family of services reads it as NOT and another as a wildcard, so we ask you to write NOT criminal or criminal! instead of guessing.
Negative proximity
NOT /N, NOT /s and NOT /p (and NOT w/N) match a section where the left side occurs at least once outside that range of the right side.
landlord NOT /s tenant matches “The landlord sues. The tenant pays.” and does not match “The landlord sues the tenant.”
That differs from landlord NOT (landlord /s tenant), which rejects the section the moment any one sentence holds both words.
Refused, never searched as words
A token that looks like an operator is either understood or refused by name. It is never quietly searched as ordinary words, because a misread operator returns a confident, wrong answer. These are refused with a422:
- a leading
!(!criminal), a doubled prefix (--x), and a double negation (NOT -x); - a placeholder left in a connector (
w/n), a connector we do not know (s/5), and any leftover/,~or^that is not one of the operators above; - a distance in sentences or paragraphs (
WITH2,SAME3): use/s,/por/N; - regular expressions (
/negligen.*/), backslash escapes, number ranges (1..5) and ranges ([2000 TO 2010]); - a case-sensitive phrase (
^"Internal Revenue"): use the case functions below; title:26, which looks like a U.S. Code title number: use thetitleNumberorcodefilters, orcite( );- any field a statute section does not have (see below).
Field restrictions
A term normally searches the section’s body text. Wrap it in a field function to search somewhere else.
Write the function name directly before the parenthesis:
title (x) is a 422.
Fields a statute section does not have are refused by name rather than ignored: dates, judges, courts, parties and the other case-law fields, annotations, credits and history notes, and search-engine fields such as site:.
Filter by year with yearFrom and yearTo, by jurisdiction with state, and by code with code or titleNumber.
For a section’s amendment history, read GET /us/statutes/section/{actId}/changes.
Case and number functions
Case functions read the text as printed, so
allcaps(irs) matches “IRS” and not “Irs”.
plural( ) adds a regular plural ending.
For an irregular plural, type the plural word itself (children).
Sentences and paragraphs in statute text
/s and /p depend on where a sentence and a paragraph end, and statute text is not prose, so the boundaries are defined for it.
They are real boundaries, not fixed word windows.
A sentence ends at a sentence-ending period, question mark or exclamation mark followed by a new sentence.
Legal abbreviations, decimals and initials do not end one: “Sec.”, “U.S.C.” and “1950.5” stay inside their sentence.
A paragraph starts at any of these:
- a blank line;
- a subsection marker such as
(a),(1),(iv),(A)or(aa)that starts a line, or follows a.,;or:; - a heading line starting
Sec.,Section,§,RuleorArticle.
(2) (a) stays one paragraph rather than leaving the (2) alone.
A section with none of these boundaries is one paragraph.
So in “(a) The landlord may recover. (b) The tenant shall pay.”, landlord /p tenant does not match: (b) after a period starts a new paragraph.
Wildcards and fuzzy terms
Rules:
- A wildcard needs at least 3 letters or digits before the first
*,!,$or?.ab*and*abilityare refused. There are no leading wildcards. - A length-limited wildcard (
$N, or a run of*) allows 1 to 5 extra characters. Use a single*for any number. - At most 5 wildcard and fuzzy terms per expression, counting those inside phrases.
- A fuzzy term allows at most 2 edits (an insertion, deletion or substitution each) and needs at least 3 letters.
- A wildcard matches letters and digits only. It never crosses a space or punctuation.
Text pasted from Word, PDFs and the web
The expression is normalized before it is read, so a search copied out of a document behaves like one typed by hand:Response fields
parsedQuery is present only when matchType is boolean.
It is your expression in canonical form: aliases replaced by the operators above, implicit phrases quoted, groups parenthesized, redundant parentheses dropped.
Sending parsedQuery back as the query runs the same search, so it is the right thing to log, cache or show to a user.
queryWarnings is present only when matchType is boolean and the expression is valid but may not mean what you intended.
It is a list of plain-English strings, and it never changes the search: the search ran as parsedQuery shows.
It flags three cases:
The field is omitted when there is nothing to warn about.
queryHint is present only when matchType is any and the query looks like a Boolean expression: an uppercase AND, OR or NOT between words, a proximity connector such as /s or /5, or atleastN(, in a query that would parse.
It means the search ran as natural language, operators included as ordinary words.
Retry with matchType: "boolean" if you meant the operators.
A Boolean-looking query is never switched to Boolean mode for you, because the same request must mean the same thing every time.
In Boolean mode:
noGoodMatchistrueonly when no section matched, andfalseotherwise. Every result matches by definition.matchQualityisnull. Its tiers are calibrated on natural-language ranking and do not describe membership in a Boolean set.relevanceScoreorders the matches, as it does in every mode. Negated terms never contribute to ranking.rankingDegraded: truemeans the order fell back to a simpler score. Every result still satisfies the expression.
Recall: what you get and what you do not
Boolean mode guarantees precision: every section returned satisfies the expression. It is not an exhaustive enumeration, and three things bound what comes back:- At most 120 results per query, as with every search (
limitup to 50,offsetup to 70). When more than 120 sections match, you get the 120 most relevant. Narrow withstate,corpusType,codeortitleNumber, or split the expression, to reach the rest. - Wildcard and fuzzy terms match the word forms found while searching.
retaliat*matches every form that turns up in the candidate sections, which in practice is every common form, but a rare form that appears only in sections the search never reached can be missed. If one form matters, write it out:retaliat* OR retaliatory. - Very long sections. When the words of an
ANDor a proximity pair sit far apart in a long section, that section is still found, but through a relevance-ranked pass, so in a broad expression it can fall outside the 120.
/s to /p, /p to AND, a phrase to its words joined by AND) or widen the scope.
To count or list every section in a body of law regardless of wording, use POST /us/statutes/count and GET /us/statutes/divisions.
See How search works.
Pricing
A Boolean search costs the same as any search: 4 credits per call. A422 for an expression we cannot read is not charged, because the expression is read before any charge starts, and a 503 from a temporary backend outage is refunded.
A valid expression that matches nothing is a completed search and is charged.
Read creditsConsumed on the response, and see GET /api-credits/pricing for the live matrix.
Limits
Limits are refused, never truncated: a search that quietly dropped part of your expression would return a different set than the one you asked for.
Coming from another service
A few differences catch people who already write terms-and-connectors searches elsewhere:AND is always written out.
Two operands next to a parenthesis with no operator between them, as in landlord tenant (deposit), are a 422 that names the missing operator.
Errors
An expression we cannot read returns422 with a detail string.
It names the problem and, where there is one, the 0-based character position in your query.
A query over 500 characters fails schema validation instead, with the usual
loc array described in Errors.
If the search backend is temporarily unavailable, the API returns 503 and does not charge. Retry with backoff.
For AI agents
Rules for writing an expression that does what you mean on the first call:- Send
matchType: "boolean". Without it the operators are searched as words, and the response carriesqueryHint. - Write operators in UPPERCASE:
AND,OR,NOT,/s,/p,/5. Lowercaseand,or,notare words. - Always write
ANDbetween concepts. A space makes a phrase:landlord tenantis the phrase “landlord tenant”, not both words. - Quote multi-word terms to make phrases explicit:
"security deposit". - Parenthesize every
ORgroup and any mix of operators. Precedence isOR, then/N,/s,/p, thenAND, thenNOT, which differs from textbook Boolean. - Prefer
/sor/ptoANDwhen two ideas must be connected, not merely present in a long section. - Use wildcards for word forms: there is no stemming, so
depositmissesdeposits. Writedeposit*, with at least 3 characters before the*, and no more than 5 wildcard or fuzzy terms. - Exclude with
NOT word. Never write!word, which is refused. - Every expression needs one positive term.
NOT xalone is refused. - Scope with request fields, not query words. Use
state,corpusType,code,titleNumber,yearFromandyearTo. Field functions exist only fortitle( ),cite( )andtext( ). - On
422, fix the expression and retry. Readdetail: it names the problem and the character position. A422costs nothing. - On
503, retry with backoff. It is a temporary backend outage and is not charged; do not change the expression. - Read
parsedQueryto confirm the grouping you intended, and log it rather than the raw string. IfqueryWarningsis present, fix the expression it names before relying on the results. - Treat an empty result as “no match in scope”, not “no such law”. Loosen (
/sto/ptoAND) or widen the scope before reporting a gap. - To fetch a known citation, do not use Boolean. Call
GET /us/statutes/resolve, or search the citation withmatchType: "any".
Related
How search works
The hybrid ranking model and every matchType.
Search API reference
Every request and response field of POST /us/statutes/search.
Best practices
Scoping, choosing a matchType, and reading the response.
Errors
Status codes and how to recover from each.

