---
title: "Search laws"
method: POST
path: "/laws/search"
---

# Search laws

`POST /laws/search`

Full-text search over statutes, regulations, constitutions, and agency
guidance (US federal + all 50 states + DC).

**Currency.** Results are the law in force TODAY by default. Currency
is *derived*, not stored: a document is current iff (1) it is not
marked historical, (2) its `effective_date` is not in the future
(a not-yet-effective amendment is stored but is not yet the law), and
(3) no newer version is already in force, and (4) it is not a
`TOMBSTONE`. Set `current_only: false` to search historical and
future-effective versions too; each result carries `is_current` and
`is_historical` so you can tell them apart. Historical search requires
an API key with full historical access.

**Filters.**
- `states` — full state names or USPS abbreviations; federal law is
  `"Federal"`. Values are validated server-side.
- `collection_types` — statute / regulation / constitution / guidance /
  executive_order / notice.
- `collections` — specific codes by id or human-readable name (see
  `/laws/collections`). Values are resolved server-side.
- `path_prefix` — restrict to a subtree of a code via its ltree path
  (e.g. `"cfr.t21"` = all of 21 CFR). Pair it with `collections`;
  paths are only unique within a collection.
- `effective_date_from/to`, `publication_date_from/to` — ISO dates,
  inclusive. Note many state statutes have no source-stated effective
  date (the field is null and such docs would be excluded by an
  effective_date range filter).

**State surveys.** `state_counts` in the response gives estimated
per-state hit counts for the whole query (not just the returned page)
— use it to scope the survey, then verify each state with a filtered
search.

**Pagination:** `page` (1-indexed) and `page_size` (max 50). Results
beyond the first 10,000 cannot be paginated; narrow the query instead.

## Request body

- LawsSearchRequest
  - `query` string, required — Full-text query, matched against document text, headings, and citations
  - `states` string[] — State names or USPS abbreviations; federal law is "Federal". Values are validated server-side.
  - `collection_types` string[]
  - `collections` string[] — Restrict to collection ids or human-readable names (see /laws/collections). Values are resolved server-side.
  - `path_prefix` string — Restrict to a subtree via a dot-separated ltree path prefix. Pair with collections — paths are only unique within a collection.
  - `effective_date_from` string, date
  - `effective_date_to` string, date
  - `publication_date_from` string, date
  - `publication_date_to` string, date
  - `current_only` boolean — When true (default), only documents that are the law in force today. Currency is derived — not historical, not future-effective, no in-force successor version.
  - `page` integer
  - `page_size` integer

## Response `200`

Search results

- LawsSearchResponse
  - `total` integer — Estimated matching documents for the whole query
  - `page` integer
  - `page_size` integer
  - `results` LawSearchResult[]
    - `id` string, uuid — Document id — use with /laws/get
    - `score` number, nullable
    - `collection_id` string
    - `collection_type` string
    - `state` string
    - `country` string
    - `path` string — ltree path within the collection
    - `node_type` 'LEAF' | 'PARENT' | 'TOMBSTONE' — LEAF is a content section; PARENT a container; TOMBSTONE a repealed/reserved placeholder
    - `number` string, nullable — Section/part number token
    - `title` string, nullable — Section title / catchline
    - `citation` string, nullable
    - `effective_date` string, date, nullable
    - `publication_date` string, date, nullable
    - `is_current` boolean — Whether this document is the law in force today (derived)
    - `is_historical` boolean — Whether the source or ingestion pipeline marks this version superseded
    - `snippets` string[] — Highlighted fragments (<em> marks matches)
    - `url` string, uri — Midpage page for this exact version
  - `state_counts` object — Estimated per-state hit counts for the whole query (not just this page). Verify each state with a filtered search.

## Other responses

- `400` — Validation error
- `401` — Unauthorized
- `403` — Historical search requires full historical access

---

[API](https://skmtc.dev/midpage/apis/midpage-data-services-api.md) · [All operations](https://skmtc.dev/midpage/apis/midpage-data-services-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/midpage/midpage-data-services-api/revisions/8d436f13cd7e/schema)
