> ## Documentation Index
> Fetch the complete documentation index at: https://vaquill.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Get a state session law's text, current or a past version

> The act's text exactly as printed, one page of about 30,000 characters at a
time, cut at a paragraph break where one is near. Follow `nextCursor` while
`hasMore` is true; `pageStart` / `pageEnd` / `totalChars` are character offsets
into the whole text, and concatenating the pages in order reproduces it.

**Cost**: 6 credits per page served; each page is charged on its own, so you can stop
whenever you have enough. `pagePrice` is what this page cost, `totalPages` the estimated pages in
all, and `estimatedRemainingCredits` the pages still to come times the price.

**Cost of reading a law.** Reading a whole law costs `estimatedBodyPages` times the price
of one body page (6 credits). `estimatedBodyPages` is on the record next to `charCount`
and is the most pages the text can take: a page holds up to 30,000 characters and is cut
back to a paragraph break, so a long act usually takes fewer. It is null when the text cannot be
read (it can be when served, or when withheld for a reason we label and `/body` reads with
`includeUnverified`). Most acts take a page or two. Each body response carries `pagePrice` and
`estimatedRemainingCredits`, so you can stop whenever you have enough.


Worked example: the longest act we hold, Ohio's 2025 budget act (HB 96, 9,571,132
characters), takes at most 399 pages, 2,394 credits to read in full.

**Where a page starts.** Follow `nextCursor` from the page before, or send `startChar`, a
character offset into the text (0-based, the scale of `pageStart` and `totalChars`), to jump to a
place you know. Send one or the other, never both (a 422, uncharged). A `startChar` page costs and
sizes the same as any other. `startChar` has no version binding of its own, so add
`expectTextSha256` (the `textSha256` you read the text under): if the text was re-collected since,
the answer is a 409 and nothing is charged. There is no page-size parameter: a page is always about
30,000 characters, so its price is fixed.

**Attribution.** Every outcome carries `citation`, `jurisdiction`, `session`, `approvedDate` and
`sourceUrl` (the official copy on a government host, present when the text is withheld or not held
too), so a page is attributable on its own.

**Id only.** This route takes a `sessionLawId`, not a citation: resolve a citation once with
`GET /us/session-laws/{sessionLawId}` and use the id it returns.

**Not served, not charged.** When we do not serve the text (`textStatus` is not `held`), the answer
is a 200 with `available: false`, a `reason` (`not_held`, `withheld`, `pending` or `empty_text`),
`creditsConsumed: 0`, the `withheldReason` for a withheld law, and the official `sourceUrl`. A
federal id (`SAL_...`) is a 404 (`federal_session_law`); read federal session laws with
`GET /us/statutes/section/{actId}`. Errors (unknown id 404, stale cursor or mismatched
`expectTextSha256` 409, malformed cursor or `startChar` 422) are not charged, and a failure on our
side (500, 503) is refunded. The parameters and the 409 response give the exact conditions.

**Past versions: `version`.** We keep every version of a law's text that we served or adopted. List
them with `GET /us/session-laws/{sessionLawId}/versions`, then send one of those numbers as
`version`; omit it for the current version. The response then names `version` and
`isCurrentVersion`, and the page, `nextCursor` and `textSha256` belong to that version. The price is
unchanged: 6
credits per page, whichever version you read. A `version` the law does not have is a 404, refunded.
Without `version` and `includeUnverified` the response is the plain current-text page.

**Text we hold back: `includeUnverified`.** A law whose text has a defect we have not cleared is
`withheld`, and by default `/body` answers `available: false`, free. Send `includeUnverified=true`
to read its text when the reason it is held back is one we can label. The page then carries
`textReliability` (`unverified`: a check has not been completed, or `known_issue`: we have evidence
of the defect), a stable `reasonCode` and a one-sentence `notice` to show beside the text: the text
may show deleted (struck) or vetoed law as if it were enacted, so check the printed act at
`sourceUrl` before relying on it. The codes that serve the text, flagged, are `markup_unverified`,
`strike_unchecked`, `struck_text_shown_as_current`, `struck_text_merged`, `veto_unchecked` and
`licence_unconfirmed`. Some text is not served even when you opt in, and answers
`available: false`, free, with the `reasonCode` and no text: a law whose licence bars use
(`licence_barred`), text that failed our own validation (`validation_failed`), a session we cannot
yet tell apart from another (`session_unresolved`), a source we have not yet audited
(`collector_unaudited`) and a reason we have not classified (`unclassified`). A served law with
`includeUnverified=true` reads as usual and says `textReliability: verified`. Such a page costs
6 credits like any other and can be combined with `version`. The fields `version`,
`isCurrentVersion`, `textReliability`, `reasonCode` and `notice` are omitted unless you asked for them.

**Amendatory markup.** An amending act prints the language it deletes and inserts. Where
`amendatoryMarkup` is `preserved`, that markup is in `text` in the convention `markupConvention`
names: `wdiff` writes deleted language `[-like this-]` and inserted language `{+like this+}`;
`publisher_literal` keeps the publisher's own markers as printed (Minnesota's `new text begin` and
`deleted text begin`); `mixed` has both. Where it is `lost`, the publisher printed markup our text
does not keep, so deleted words can read as law: check the source before quoting. Only the as-printed
text is served; there is no clean "as enacted" view.

**Example**

```bash
curl "https://api.vaquill.ai/api/v1/us/session-laws/SSL_MN_2025S1_G_Y2025_C1/body" \
  -H "Authorization: Bearer $VAQUILL_API_KEY"

# jump to a character offset, pinned to the version of the text you read
curl "https://api.vaquill.ai/api/v1/us/session-laws/SSL_MN_2025S1_G_Y2025_C1/body?startChar=29987&expectTextSha256=02693d5b55d4709b" \
  -H "Authorization: Bearer $VAQUILL_API_KEY"

# an older version (list the versions first at .../versions), or a withheld law's labelled text
curl "https://api.vaquill.ai/api/v1/us/session-laws/SSL_MN_2025S1_G_Y2025_C1/body?version=1" \
  -H "Authorization: Bearer $VAQUILL_API_KEY"
curl "https://api.vaquill.ai/api/v1/us/session-laws/SSL_LA_2025R_G_C2/body?includeUnverified=true" \
  -H "Authorization: Bearer $VAQUILL_API_KEY"
```

```javascript
const MY_BUDGET = 100; // the most you will spend to finish reading, in credits
let cursor;
let text = "";
do {
  const url = new URL("https://api.vaquill.ai/api/v1/us/session-laws/SSL_MN_2025S1_G_Y2025_C1/body");
  if (cursor) url.searchParams.set("cursor", cursor);
  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${process.env.VAQUILL_API_KEY}` },
  });
  const page = await res.json();
  if (!page.available) break; // withheld or not held: page.sourceUrl is the official copy
  text += page.text;
  if (page.estimatedRemainingCredits > MY_BUDGET) break; // stop whenever you have enough
  cursor = page.nextCursor;
} while (cursor);
```

**Related endpoints**

- `GET /us/statutes/resolve` answers a citation that names a state session law rather than a
  code section with a `sessionLaw` block (`matched`, or `ambiguous` with every candidate),
  pointing here. It never changes `resolved` or `section`.
- `GET /us/statutes/coverage` lists, per jurisdiction under `sessionLaws`, the sessions held and
  whether each is `complete` or `partial`. A law missing from a `partial` session may still exist.
- Federal session laws (the Statutes at Large, `SAL_` ids) are read with
  `GET /us/statutes/section/{actId}`, not here.

**Nulls.** Every response field is present: one with no value is `null` (`[]` for a list). The
examples here leave the nulls out. `publisher`, `provenance` and `session.coverageStatus` on a law,
and `coverage` on a list page with rows, are absent when they do not apply.

**Rate limits.** Calls count against your key's per-minute budget like every Data API route; a 429
carries `Retry-After`.



## OpenAPI

````yaml https://api.vaquill.ai/external/openapi.json get /api/v1/us/session-laws/{session_law_id}/body
openapi: 3.1.0
info:
  title: Vaquill Developer API
  description: >-
    Public API for legal statutes and legislation.


    **Authentication**: Pass your API key as `Authorization: Bearer vq_key_...`
    (preferred) or in the `X-API-Key` header. Sending two different keys in one
    request is rejected with a 401.


    **Credits**: Each call costs API credits. See `GET
    /api/v1/api-credits/pricing` for the full pricing matrix.


    ## Jurisdictions


    | Jurisdiction | Coverage | `countryCode` |

    |---|---|---|

    | **United States** | USC and the Statutes at Large, the CFR and its annual
    editions, all 56 state and territory statutory codes (50 states, DC and five
    territories), state administrative regulations, court rules, federal and
    state constitutions, federal agency guidance and adjudications, the Federal
    Register, the Sentencing Guidelines and US tax treaties. | `US` |


    See the full [Coverage page](https://www.vaquill.ai/docs/api-guide/coverage)
    for the jurisdiction-by-jurisdiction breakdown, or call
    `/us/statutes/coverage` for live counts. Coverage is per (jurisdiction,
    corpusType) pair, so treat that endpoint as the authoritative list rather
    than this summary.


    ## Endpoints


    - **US Statutes**: Search and retrieve any of the corpora above with full
    text, resolve a citation to its exact section, browse the statutory
    hierarchy, read a section as it stood on a past date, and follow its change
    history, cross-references and defined terms

    - **Board Watches**: Subscribe to a corpus source and get a webhook or email
    when it refreshes with real changes (free, API key required)

    - **Pricing**: Credit costs per endpoint (no auth required)


    ## Rate limits


    Limits are enforced per API key and scale with your plan. A `429` response
    includes a `Retry-After` header.


    | Plan | Per minute | Per hour | Per day |

    |---|---|---|---|

    | Vaquill API Pro | 60 | 1,000 | 2,000 |

    | Vaquill API Business | 150 | 2,500 | 10,000 |


    For full documentation, visit the [API
    Reference](https://www.vaquill.ai/docs/api-reference/).
  version: 1.0.0+a1f3e4af5900e02d
  contact:
    name: Vaquill API Support
    url: https://www.vaquill.ai
    email: support@vaquill.ai
  license:
    name: Proprietary
    url: https://www.vaquill.ai/terms
  termsOfService: https://www.vaquill.ai/terms
  x-revision: a1f3e4af5900e02d
servers:
  - url: https://api.vaquill.ai
    description: Production
security:
  - ApiKeyAuth: []
  - ApiKeyHeader: []
tags:
  - name: US Statutes
    description: >-
      Search and retrieve US primary law. Covers the United States Code and the
      Statutes at Large, the Code of Federal Regulations and its annual
      editions, state statutory codes and administrative regulations, federal
      and state constitutions, court rules, Federal Register rules and
      Presidential documents, federal and state agency guidance, agency
      adjudications, state Attorney General opinions, the Sentencing Guidelines
      and US tax treaties. Scope a search with the `corpusType` filter, and call
      `/us/statutes/coverage` for the live jurisdiction-by-corpusType list.


      - **Search**: Search across all USC, CFR, state, and regulatory sections

      - **Section**: Get metadata, citation, hierarchy, and source links for a
      specific section

      - **Body**: Get the full text of a section

      - **Enactments**: Which state session laws a publisher's own tables list
      against a section (supported jurisdictions only, never a complete history)
  - name: US Session Laws
    description: >-
      State session laws: the acts of each legislature as they were enacted,
      chapter by chapter, before they are folded into a code. A session law is
      what the governor signs. It carries the act's own text, including the
      language it strikes and inserts, its approval and effective dates, and,
      where the publisher prints one, the code sections it changes. That makes
      it the source for "which act changed this section, and when did it take
      effect".


      Every act has a permanent `sessionLawId` (for example
      `SSL_MN_2025R_G_Y2025_C1`, Minnesota Laws 2025, regular session, chapter
      1) whether or not we hold its text, and a citation or bill number such as
      `S.F.No. 1552` is accepted where an id goes. v1 serves STATE acts only.
      Federal session laws (the Statutes at Large, `SAL_` ids) are served by
      `/us/statutes/section`, and `/us/statutes/resolve` points a session-law
      citation here.


      **Start here**: check `/us/statutes/coverage` (free) for what we hold per
      state: each jurisdiction's `sessionLaws` block lists its sessions, which
      are complete or only partly collected, and the `series` and
      `instrumentTypes` that exist. Then **List** a session or a date range to
      get ids, **Get** one act for its record, then **Body** for its text. A law
      missing from a partly collected session is a free 404
      (`session_not_fully_collected`), not proof it does not exist.


      - **List**: everything enacted in a state's session, approved in a window,
      or taking effect on a date

      - **Get**: one act by id or by citation; dates (`effectiveDates` is always
      a list), sources and the code sections it affects

      - **Body**: the act's text as printed, paged by cursor, with amendatory
      markup preserved where the publisher printed it

      - **Batch**: up to 50 ids or citations in one call, the same record as
      Get, billed per law served, with every miss listed and its reason

      - **Changes**: a sync feed of the registry over an integer cursor
      (`sinceId`): what began to be served, was corrected, withdrawn or merged


      The reverse link, from a code section to the acts a publisher's own tables
      list against it, is `GET /us/statutes/section/{actId}/enactments`.
  - name: US Rulemaking
    description: >-
      How a federal rule is made, as public records tied together by its
      Regulation Identifier Number (RIN): the semiannual Unified Agenda (every
      edition from Fall 1995), the OIRA review under Executive Order 12866, the
      Regulations.gov docket and its documents, and the Federal Register
      documents that proposed and finalised it.


      **Start here**: `GET /us/rulemaking/coverage` (free) lists what is held
      per source and whether each is fresh. Then **By RIN** for everything held
      for one rule, **Agenda history** for how its timetable moved edition by
      edition, or **Dockets** and **Documents** for the Regulations.gov side.


      Every link between sources carries its `basis` and `quality` (`verified`,
      `candidate`, `ambiguous`). A link we could not make with confidence is
      marked, never guessed, and an umbrella RIN shared by unrelated rules
      claims no proposal-to-final pairing. A comment count of `null` means not
      measured, never zero. Comment text, attachments and commenter information
      are not held or served.
  - name: Board Watches
    description: >-
      Law-change alerts. Subscribe to a **board** (a tracked corpus source,
      identified by `corpusType` plus an optional `state`) and get a webhook or
      email whenever it refreshes with real changes, naming the exact sections
      that changed. Fetch old-vs-new text for any amended section via the change
      diff.


      Boards refresh on their own existing cadence; watching one does not change
      how often it refreshes. Every endpoint here is **free**: authenticated by
      API key and rate-limited, but not credit-metered.


      See the [Law Change Alerts
      guide](https://www.vaquill.ai/docs/api-guide/alerts) for the full
      walkthrough.
  - name: Pricing
    description: >-
      Credit pricing and conversion rates. No authentication required. 1 credit
      = $0.01 USD.
  - name: Agent Onboarding
    description: >-
      How an AI agent gets an API key for its human, with no copy and paste.
      Free and keyless. The agent starts a signup, the human approves a short
      code while signed in, and the agent collects an ordinary API key. Full
      walkthrough: https://api.vaquill.ai/auth.md
  - name: Credits
    description: >-
      Your own credit balance: what is spendable right now, where it came from,
      and what is about to expire.


      Free and never charged, so it is safe to poll for low-balance alerting or
      to pre-flight a batch job.
externalDocs:
  description: Full API Reference
  url: https://www.vaquill.ai/docs/api-reference/
paths:
  /api/v1/us/session-laws/{session_law_id}/body:
    get:
      tags:
        - US Session Laws
      summary: Get a state session law's text, current or a past version
      description: >-
        The act's text exactly as printed, one page of about 30,000 characters
        at a

        time, cut at a paragraph break where one is near. Follow `nextCursor`
        while

        `hasMore` is true; `pageStart` / `pageEnd` / `totalChars` are character
        offsets

        into the whole text, and concatenating the pages in order reproduces it.


        **Cost**: 6 credits per page served; each page is charged on its own, so
        you can stop

        whenever you have enough. `pagePrice` is what this page cost,
        `totalPages` the estimated pages in

        all, and `estimatedRemainingCredits` the pages still to come times the
        price.


        **Cost of reading a law.** Reading a whole law costs
        `estimatedBodyPages` times the price

        of one body page (6 credits). `estimatedBodyPages` is on the record next
        to `charCount`

        and is the most pages the text can take: a page holds up to 30,000
        characters and is cut

        back to a paragraph break, so a long act usually takes fewer. It is null
        when the text cannot be

        read (it can be when served, or when withheld for a reason we label and
        `/body` reads with

        `includeUnverified`). Most acts take a page or two. Each body response
        carries `pagePrice` and

        `estimatedRemainingCredits`, so you can stop whenever you have enough.



        Worked example: the longest act we hold, Ohio's 2025 budget act (HB 96,
        9,571,132

        characters), takes at most 399 pages, 2,394 credits to read in full.


        **Where a page starts.** Follow `nextCursor` from the page before, or
        send `startChar`, a

        character offset into the text (0-based, the scale of `pageStart` and
        `totalChars`), to jump to a

        place you know. Send one or the other, never both (a 422, uncharged). A
        `startChar` page costs and

        sizes the same as any other. `startChar` has no version binding of its
        own, so add

        `expectTextSha256` (the `textSha256` you read the text under): if the
        text was re-collected since,

        the answer is a 409 and nothing is charged. There is no page-size
        parameter: a page is always about

        30,000 characters, so its price is fixed.


        **Attribution.** Every outcome carries `citation`, `jurisdiction`,
        `session`, `approvedDate` and

        `sourceUrl` (the official copy on a government host, present when the
        text is withheld or not held

        too), so a page is attributable on its own.


        **Id only.** This route takes a `sessionLawId`, not a citation: resolve
        a citation once with

        `GET /us/session-laws/{sessionLawId}` and use the id it returns.


        **Not served, not charged.** When we do not serve the text (`textStatus`
        is not `held`), the answer

        is a 200 with `available: false`, a `reason` (`not_held`, `withheld`,
        `pending` or `empty_text`),

        `creditsConsumed: 0`, the `withheldReason` for a withheld law, and the
        official `sourceUrl`. A

        federal id (`SAL_...`) is a 404 (`federal_session_law`); read federal
        session laws with

        `GET /us/statutes/section/{actId}`. Errors (unknown id 404, stale cursor
        or mismatched

        `expectTextSha256` 409, malformed cursor or `startChar` 422) are not
        charged, and a failure on our

        side (500, 503) is refunded. The parameters and the 409 response give
        the exact conditions.


        **Past versions: `version`.** We keep every version of a law's text that
        we served or adopted. List

        them with `GET /us/session-laws/{sessionLawId}/versions`, then send one
        of those numbers as

        `version`; omit it for the current version. The response then names
        `version` and

        `isCurrentVersion`, and the page, `nextCursor` and `textSha256` belong
        to that version. The price is

        unchanged: 6

        credits per page, whichever version you read. A `version` the law does
        not have is a 404, refunded.

        Without `version` and `includeUnverified` the response is the plain
        current-text page.


        **Text we hold back: `includeUnverified`.** A law whose text has a
        defect we have not cleared is

        `withheld`, and by default `/body` answers `available: false`, free.
        Send `includeUnverified=true`

        to read its text when the reason it is held back is one we can label.
        The page then carries

        `textReliability` (`unverified`: a check has not been completed, or
        `known_issue`: we have evidence

        of the defect), a stable `reasonCode` and a one-sentence `notice` to
        show beside the text: the text

        may show deleted (struck) or vetoed law as if it were enacted, so check
        the printed act at

        `sourceUrl` before relying on it. The codes that serve the text,
        flagged, are `markup_unverified`,

        `strike_unchecked`, `struck_text_shown_as_current`,
        `struck_text_merged`, `veto_unchecked` and

        `licence_unconfirmed`. Some text is not served even when you opt in, and
        answers

        `available: false`, free, with the `reasonCode` and no text: a law whose
        licence bars use

        (`licence_barred`), text that failed our own validation
        (`validation_failed`), a session we cannot

        yet tell apart from another (`session_unresolved`), a source we have not
        yet audited

        (`collector_unaudited`) and a reason we have not classified
        (`unclassified`). A served law with

        `includeUnverified=true` reads as usual and says `textReliability:
        verified`. Such a page costs

        6 credits like any other and can be combined with `version`. The fields
        `version`,

        `isCurrentVersion`, `textReliability`, `reasonCode` and `notice` are
        omitted unless you asked for them.


        **Amendatory markup.** An amending act prints the language it deletes
        and inserts. Where

        `amendatoryMarkup` is `preserved`, that markup is in `text` in the
        convention `markupConvention`

        names: `wdiff` writes deleted language `[-like this-]` and inserted
        language `{+like this+}`;

        `publisher_literal` keeps the publisher's own markers as printed
        (Minnesota's `new text begin` and

        `deleted text begin`); `mixed` has both. Where it is `lost`, the
        publisher printed markup our text

        does not keep, so deleted words can read as law: check the source before
        quoting. Only the as-printed

        text is served; there is no clean "as enacted" view.


        **Example**


        ```bash

        curl
        "https://api.vaquill.ai/api/v1/us/session-laws/SSL_MN_2025S1_G_Y2025_C1/body"
        \
          -H "Authorization: Bearer $VAQUILL_API_KEY"

        # jump to a character offset, pinned to the version of the text you read

        curl
        "https://api.vaquill.ai/api/v1/us/session-laws/SSL_MN_2025S1_G_Y2025_C1/body?startChar=29987&expectTextSha256=02693d5b55d4709b"
        \
          -H "Authorization: Bearer $VAQUILL_API_KEY"

        # an older version (list the versions first at .../versions), or a
        withheld law's labelled text

        curl
        "https://api.vaquill.ai/api/v1/us/session-laws/SSL_MN_2025S1_G_Y2025_C1/body?version=1"
        \
          -H "Authorization: Bearer $VAQUILL_API_KEY"
        curl
        "https://api.vaquill.ai/api/v1/us/session-laws/SSL_LA_2025R_G_C2/body?includeUnverified=true"
        \
          -H "Authorization: Bearer $VAQUILL_API_KEY"
        ```


        ```javascript

        const MY_BUDGET = 100; // the most you will spend to finish reading, in
        credits

        let cursor;

        let text = "";

        do {
          const url = new URL("https://api.vaquill.ai/api/v1/us/session-laws/SSL_MN_2025S1_G_Y2025_C1/body");
          if (cursor) url.searchParams.set("cursor", cursor);
          const res = await fetch(url, {
            headers: { Authorization: `Bearer ${process.env.VAQUILL_API_KEY}` },
          });
          const page = await res.json();
          if (!page.available) break; // withheld or not held: page.sourceUrl is the official copy
          text += page.text;
          if (page.estimatedRemainingCredits > MY_BUDGET) break; // stop whenever you have enough
          cursor = page.nextCursor;
        } while (cursor);

        ```


        **Related endpoints**


        - `GET /us/statutes/resolve` answers a citation that names a state
        session law rather than a
          code section with a `sessionLaw` block (`matched`, or `ambiguous` with every candidate),
          pointing here. It never changes `resolved` or `section`.
        - `GET /us/statutes/coverage` lists, per jurisdiction under
        `sessionLaws`, the sessions held and
          whether each is `complete` or `partial`. A law missing from a `partial` session may still exist.
        - Federal session laws (the Statutes at Large, `SAL_` ids) are read with
          `GET /us/statutes/section/{actId}`, not here.

        **Nulls.** Every response field is present: one with no value is `null`
        (`[]` for a list). The

        examples here leave the nulls out. `publisher`, `provenance` and
        `session.coverageStatus` on a law,

        and `coverage` on a list page with rows, are absent when they do not
        apply.


        **Rate limits.** Calls count against your key's per-minute budget like
        every Data API route; a 429

        carries `Retry-After`.
      operationId: get_session_law_body
      parameters:
        - name: session_law_id
          in: path
          required: true
          schema:
            type: string
            minLength: 1
            maxLength: 300
            description: >-
              A state session law's id, for example `SSL_MN_2025S1_G_Y2025_C1`,
              from a `/us/session-laws/list` result.


              A citation also works here on `GET
              /us/session-laws/{sessionLawId}`, and `resolvedFrom` says what
              your input matched. Name the state in the citation: `Minn. Laws
              2025, ch. 1`, `2025 Minn. Laws ch. 1`, `Ch. 1, Laws of Minnesota
              2025`, `Ch. 2025-12, Laws of Fla.`, `2025 Wash. Sess. Laws ch.
              12`, `La. Acts 2025, No. 12`, `Pa. Act 12 of 2025`, `Minn. S.F.
              1552 (2025)`, `MN: Laws 2025, ch. 1`. A form only one state uses
              needs no state: `P.A. 104-0001` (Illinois), `Pub. Act No. 26-151`
              (Connecticut), `S.L. 2025-12` (North Carolina), `Stats. 2025, ch.
              12` (California), `D.C. Law 25-713`. The publisher's printed form
              (`CHAPTER 2025-12`, `S.F.No. 1552`) and the `citation` we print on
              every law also work. A form several states share (`Laws 2025, ch.
              1`, `HB 123`, `Act 12 of 2025`) is a 404 with `reason:
              needs_jurisdiction`, the states it exists in and one candidate per
              state: we never guess the state. A citation naming several laws of
              one state (Minnesota 2025 has two Chapter 1s) is a 404 listing all
              of them, `candidateCount` and `truncated` saying whether the list
              is complete, and `defaultSessionLawId` the regular session's law
              where there is exactly one conventional reading. An id or citation
              that matches nothing in a session we have only partly collected is
              a 404 with `reason: session_not_fully_collected` and that
              session's coverage: the law may exist and not be held yet, so it
              is never charged, the resolve price included. A citation costs the
              route's price PLUS the `/us/statutes/resolve` price (2 credits),
              the second kept whether or not it resolves (an unresolved citation
              is a charged verdict) and refunded on an ambiguous citation
              (several laws carry it and none is chosen, so nothing resolved),
              on a partly collected session, on a citation we could not read as
              a state session-law citation at all (its detail lists the accepted
              forms) or on a failure. URL-encode the citation; one containing
              `/` cannot travel in a path segment.


              Federal session laws (`SAL_...`, `Pub. L. 118-5`, the Statutes at
              Large) are served by `/us/statutes/section`, not here, and code
              citations (`26 U.S.C. § 1`) by `/us/statutes/resolve`.
            examples:
              - SSL_MN_2025S1_G_Y2025_C1
            title: Session Law Id
          description: >-
            A state session law's id, for example `SSL_MN_2025S1_G_Y2025_C1`,
            from a `/us/session-laws/list` result.


            A citation also works here on `GET /us/session-laws/{sessionLawId}`,
            and `resolvedFrom` says what your input matched. Name the state in
            the citation: `Minn. Laws 2025, ch. 1`, `2025 Minn. Laws ch. 1`,
            `Ch. 1, Laws of Minnesota 2025`, `Ch. 2025-12, Laws of Fla.`, `2025
            Wash. Sess. Laws ch. 12`, `La. Acts 2025, No. 12`, `Pa. Act 12 of
            2025`, `Minn. S.F. 1552 (2025)`, `MN: Laws 2025, ch. 1`. A form only
            one state uses needs no state: `P.A. 104-0001` (Illinois), `Pub. Act
            No. 26-151` (Connecticut), `S.L. 2025-12` (North Carolina), `Stats.
            2025, ch. 12` (California), `D.C. Law 25-713`. The publisher's
            printed form (`CHAPTER 2025-12`, `S.F.No. 1552`) and the `citation`
            we print on every law also work. A form several states share (`Laws
            2025, ch. 1`, `HB 123`, `Act 12 of 2025`) is a 404 with `reason:
            needs_jurisdiction`, the states it exists in and one candidate per
            state: we never guess the state. A citation naming several laws of
            one state (Minnesota 2025 has two Chapter 1s) is a 404 listing all
            of them, `candidateCount` and `truncated` saying whether the list is
            complete, and `defaultSessionLawId` the regular session's law where
            there is exactly one conventional reading. An id or citation that
            matches nothing in a session we have only partly collected is a 404
            with `reason: session_not_fully_collected` and that session's
            coverage: the law may exist and not be held yet, so it is never
            charged, the resolve price included. A citation costs the route's
            price PLUS the `/us/statutes/resolve` price (2 credits), the second
            kept whether or not it resolves (an unresolved citation is a charged
            verdict) and refunded on an ambiguous citation (several laws carry
            it and none is chosen, so nothing resolved), on a partly collected
            session, on a citation we could not read as a state session-law
            citation at all (its detail lists the accepted forms) or on a
            failure. URL-encode the citation; one containing `/` cannot travel
            in a path segment.


            Federal session laws (`SAL_...`, `Pub. L. 118-5`, the Statutes at
            Large) are served by `/us/statutes/section`, not here, and code
            citations (`26 U.S.C. § 1`) by `/us/statutes/resolve`.
        - name: cursor
          in: query
          required: false
          schema:
            anyOf:
              - type: string
                maxLength: 600
              - type: 'null'
            description: >-
              Where to resume: the previous page's `nextCursor`, unchanged. Omit
              for the first page. It is opaque, signed and tied to the exact
              text it was cut from: a value we did not issue (`reason:
              invalid_cursor`), from an older cursor format (`cursor_expired`)
              or past the end of the text (`cursor_past_end`) is a 422, and one
              from before the text was re-collected is a 409 (start again
              without it). None is charged. Send either `cursor` or `startChar`,
              never both (a 422, never charged).
            examples:
              - >-
                eyJ2IjoyLCJvIjoyOTk4NywiaCI6IjAyNjkzZDViNTVkNDcwOWIifQ.stWHVSgGqJPIElcTLfAGHA
            title: Cursor
          description: >-
            Where to resume: the previous page's `nextCursor`, unchanged. Omit
            for the first page. It is opaque, signed and tied to the exact text
            it was cut from: a value we did not issue (`reason:
            invalid_cursor`), from an older cursor format (`cursor_expired`) or
            past the end of the text (`cursor_past_end`) is a 422, and one from
            before the text was re-collected is a 409 (start again without it).
            None is charged. Send either `cursor` or `startChar`, never both (a
            422, never charged).
        - name: startChar
          in: query
          required: false
          schema:
            anyOf:
              - type: integer
                maximum: 100000000
                minimum: 0
              - type: 'null'
            description: >-
              Start the page at this character offset into the text (0-based,
              the same scale as `pageStart` and `totalChars`): an alternative to
              `cursor` for jumping to a place you already know, such as where a
              section begins. The page is the same size and price as any other
              and its `nextCursor` is a normal signed cursor. Send either
              `startChar` or `cursor`, never both (a 422, never charged). 0 to
              100,000,000; a value at or beyond the end of the text is a 422 and
              is refunded. There is no page-size parameter: the price per page
              is fixed. A short law is one page whatever you pass, so jumping
              into it saves no credit.
            examples:
              - 29987
            title: Startchar
          description: >-
            Start the page at this character offset into the text (0-based, the
            same scale as `pageStart` and `totalChars`): an alternative to
            `cursor` for jumping to a place you already know, such as where a
            section begins. The page is the same size and price as any other and
            its `nextCursor` is a normal signed cursor. Send either `startChar`
            or `cursor`, never both (a 422, never charged). 0 to 100,000,000; a
            value at or beyond the end of the text is a 422 and is refunded.
            There is no page-size parameter: the price per page is fixed. A
            short law is one page whatever you pass, so jumping into it saves no
            credit.
        - name: expectTextSha256
          in: query
          required: false
          schema:
            anyOf:
              - type: string
                pattern: ^[0-9a-f]{16,64}$
              - type: 'null'
            description: >-
              The `textSha256` you read the text under, in lowercase hex (the
              whole 64 characters, or any prefix of 16 or more). When this law's
              text no longer has that hash (it was re-collected), the answer is
              a 409 and nothing is charged, exactly as for a `cursor` cut from
              an earlier version: use it with `startChar`, which otherwise has
              no version binding of its own. Anything that is not 16 to 64
              lowercase hex characters is a 422.
            examples:
              - 02693d5b55d4709bdd36fdccee4a9737d2655a3988a90daeb6b7c486ce50260b
            title: Expecttextsha256
          description: >-
            The `textSha256` you read the text under, in lowercase hex (the
            whole 64 characters, or any prefix of 16 or more). When this law's
            text no longer has that hash (it was re-collected), the answer is a
            409 and nothing is charged, exactly as for a `cursor` cut from an
            earlier version: use it with `startChar`, which otherwise has no
            version binding of its own. Anything that is not 16 to 64 lowercase
            hex characters is a 422.
        - name: version
          in: query
          required: false
          schema:
            anyOf:
              - type: integer
                maximum: 100
                minimum: 1
              - type: 'null'
            description: >-
              Read this version of the act's text instead of the current one: a
              `version` from `GET /us/session-laws/{sessionLawId}/versions`.
              Omit for the current version. The page, its `nextCursor` and
              `textSha256` belong to that version's text, so a cursor from one
              version is a 409 on another. A number that is not one of the law's
              listed versions is a 404 and is refunded; a value below 1 is a 422
              and is never charged. Priced as any body page. On a law we hold
              back, an older version is readable only with
              `includeUnverified=true`, exactly as its current text is.
            examples:
              - 1
            title: Version
          description: >-
            Read this version of the act's text instead of the current one: a
            `version` from `GET /us/session-laws/{sessionLawId}/versions`. Omit
            for the current version. The page, its `nextCursor` and `textSha256`
            belong to that version's text, so a cursor from one version is a 409
            on another. A number that is not one of the law's listed versions is
            a 404 and is refunded; a value below 1 is a 422 and is never
            charged. Priced as any body page. On a law we hold back, an older
            version is readable only with `includeUnverified=true`, exactly as
            its current text is.
        - name: includeUnverified
          in: query
          required: false
          schema:
            type: boolean
            description: >-
              Opt in to the TEXT of a law we hold but do not serve (`textStatus:
              withheld`). Default `false`: such a law answers `available:
              false`, as before, and nothing else changes. With `true` its text
              is returned when the reason it is held back is one we can label,
              and every page then carries `textReliability` (`unverified` or
              `known_issue`), `reasonCode` and a `notice` to show beside the
              text: the text may show deleted or vetoed law as if it were
              enacted. A law whose licence bars use, or whose text failed our
              own validation, is never served, opted in or not (`available:
              false` with a `reasonCode`). Priced as any body page. A served law
              answers as usual, with `textReliability: verified`.
            examples:
              - true
            default: false
            title: Includeunverified
          description: >-
            Opt in to the TEXT of a law we hold but do not serve (`textStatus:
            withheld`). Default `false`: such a law answers `available: false`,
            as before, and nothing else changes. With `true` its text is
            returned when the reason it is held back is one we can label, and
            every page then carries `textReliability` (`unverified` or
            `known_issue`), `reasonCode` and a `notice` to show beside the text:
            the text may show deleted or vetoed law as if it were enacted. A law
            whose licence bars use, or whose text failed our own validation, is
            never served, opted in or not (`available: false` with a
            `reasonCode`). Priced as any body page. A served law answers as
            usual, with `textReliability: verified`.
        - name: Idempotency-Key
          in: header
          required: false
          schema:
            anyOf:
              - type: string
                minLength: 16
                maxLength: 255
                pattern: ^[\x21-\x7e]+$
              - type: 'null'
            description: >-
              Optional. 16 to 255 visible ASCII characters (a UUIDv4 works).
              Repeating the same request with the same key replays the original
              2xx response for 24 hours without charging again. The same key on
              a different request is rejected. With the account's
              `cacheQueryDerivedData` retention setting off, no body is stored
              and a retry answers 409 `idempotency_replay_unavailable`, still
              without a second charge.
            examples:
              - 3f9c2a1e-7b44-4d0a-9c1e-5a6b7c8d9e0f
            title: Idempotency-Key
          description: >-
            Optional. 16 to 255 visible ASCII characters (a UUIDv4 works).
            Repeating the same request with the same key replays the original
            2xx response for 24 hours without charging again. The same key on a
            different request is rejected. With the account's
            `cacheQueryDerivedData` retention setting off, no body is stored and
            a retry answers 409 `idempotency_replay_unavailable`, still without
            a second charge.
      responses:
        '200':
          description: >-
            One page of the act's text, or `available: false` (not charged) when
            we do not serve it.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionLawBodyResponse'
              examples:
                firstPage:
                  summary: Page 1 of a long act (text abbreviated here)
                  value:
                    sessionLawId: SSL_MN_2025S1_G_Y2025_C1
                    citation: CHAPTER 1--S.F.No. 3
                    jurisdiction: mn
                    session:
                      code: 2025S1
                      label: 2025 1st Special Session
                      type: special
                      year: 2025
                    approvedDate: '2025-06-14'
                    approvedDateDerived: false
                    sourceUrl: >-
                      https://www.revisor.mn.gov/laws/2025/1/Session+Law/Chapter/1/
                    available: true
                    textStatus: held
                    text: >-
                      CHAPTER 1--S.F.No. 3


                      An act


                      relating to state government; appropriating money for
                      environment and natural resources; appropriating money
                      from environment and natural resources trust fund;
                      modifying prior appropriations; modifying fees and
                      surcharges; ...
                    pageStart: 0
                    pageEnd: 29987
                    totalChars: 310454
                    totalPages: 13
                    pagePrice: 6
                    estimatedRemainingCredits: 72
                    textSha256: >-
                      02693d5b55d4709bdd36fdccee4a9737d2655a3988a90daeb6b7c486ce50260b
                    amendatoryMarkup: preserved
                    markupConvention: publisher_literal
                    nextCursor: >-
                      eyJ2IjoyLCJvIjoyOTk4NywiaCI6IjAyNjkzZDViNTVkNDcwOWIifQ.stWHVSgGqJPIElcTLfAGHA
                    hasMore: true
                    processingTimeMs: 612.3
                    creditsConsumed: 6
                startChar:
                  summary: >-
                    startChar=29987: the page that begins where page 1 ended, no
                    cursor needed
                  value:
                    sessionLawId: SSL_MN_2025S1_G_Y2025_C1
                    citation: CHAPTER 1--S.F.No. 3
                    jurisdiction: mn
                    session:
                      code: 2025S1
                      label: 2025 1st Special Session
                      type: special
                      year: 2025
                    approvedDate: '2025-06-14'
                    approvedDateDerived: false
                    sourceUrl: >-
                      https://www.revisor.mn.gov/laws/2025/1/Session+Law/Chapter/1/
                    available: true
                    textStatus: held
                    text: >-
                      ...(continues at character 29987, cut at the paragraph
                      break before it) ...
                    pageStart: 29987
                    pageEnd: 59974
                    totalChars: 310454
                    totalPages: 13
                    pagePrice: 6
                    estimatedRemainingCredits: 66
                    textSha256: >-
                      02693d5b55d4709bdd36fdccee4a9737d2655a3988a90daeb6b7c486ce50260b
                    amendatoryMarkup: preserved
                    markupConvention: publisher_literal
                    nextCursor: >-
                      eyJ2IjoyLCJvIjo1OTk3NCwiaCI6IjAyNjkzZDViNTVkNDcwOWIifQ.9KqnMFXT9SmUwN9e7TzHKA
                    hasMore: true
                    processingTimeMs: 612.3
                    creditsConsumed: 6
                onePageAct:
                  summary: >-
                    A short act is one page: the last page has no nextCursor and
                    nothing remains
                  value:
                    sessionLawId: SSL_MN_2025R_G_Y2025_C1
                    citation: CHAPTER 1--S.F.No. 1552
                    jurisdiction: mn
                    session:
                      code: 2025R
                      label: 2025 Regular Session
                      type: regular
                      year: 2025
                    approvedDate: '2025-03-17'
                    approvedDateDerived: false
                    sourceUrl: >-
                      https://www.revisor.mn.gov/laws/2025/0/Session+Law/Chapter/1/
                    available: true
                    textStatus: held
                    text: >-
                      CHAPTER 1--S.F.No. 1552


                      An act


                      relating to agriculture; modifying financial reporting
                      requirements for grain buyers; amending Minnesota Statutes
                      2024, section 223.17, subdivision 6. ...
                    pageStart: 0
                    pageEnd: 5470
                    totalChars: 5470
                    totalPages: 1
                    pagePrice: 6
                    estimatedRemainingCredits: 0
                    textSha256: >-
                      55c7a8d08647e41f87e23fc2016881a6583911a1d5cfa8687403442e9096451b
                    amendatoryMarkup: preserved
                    markupConvention: publisher_literal
                    hasMore: false
                    processingTimeMs: 318.9
                    creditsConsumed: 6
                withheld:
                  summary: 'A withheld law: available false, nothing charged'
                  value:
                    sessionLawId: SSL_LA_2025R_G_C2
                    citation: ACT No. 2
                    jurisdiction: la
                    session:
                      code: 2025R
                      label: 2025 Regular Session
                      type: regular
                      year: 2025
                    approvedDate: '2025-06-20'
                    approvedDateDerived: false
                    sourceUrl: https://www.legis.la.gov/legis/ViewDocument.aspx?d=1426048
                    available: false
                    reason: withheld
                    textStatus: withheld
                    withheldReason: >-
                      LA: struck (deleted) law is merged into the text as if
                      current while the record declares the markup preserved or
                      absent (audit 2026-10-03). Awaiting a re-run with strike
                      and underline recovery.
                    pagePrice: 0
                    amendatoryMarkup: absent
                    hasMore: false
                    processingTimeMs: 41.7
                    creditsConsumed: 0
                olderVersion:
                  summary: >-
                    version=1: the first version of the text, before it was
                    re-collected. `isCurrentVersion` is false and the hash,
                    length and cursor are that version's
                  value:
                    sessionLawId: SSL_MN_2025S1_G_Y2025_C1
                    citation: CHAPTER 1--S.F.No. 3
                    jurisdiction: mn
                    session:
                      code: 2025S1
                      label: 2025 1st Special Session
                      type: special
                      year: 2025
                    approvedDate: '2025-06-14'
                    approvedDateDerived: false
                    sourceUrl: >-
                      https://www.revisor.mn.gov/laws/2025/1/Session+Law/Chapter/1/
                    available: true
                    textStatus: held
                    text: >-
                      CHAPTER 1--S.F.No. 3


                      An act


                      relating to state government; appropriating money for
                      environment and natural resources; appropriating money
                      from environment and natural resources trust fund;
                      modifying prior appropriations; modifying fees and
                      surcharges; ...
                    pageStart: 0
                    pageEnd: 29931
                    totalChars: 309876
                    totalPages: 13
                    pagePrice: 6
                    estimatedRemainingCredits: 72
                    textSha256: >-
                      b4e1a07c95d3f6280c1d7a3e5f9b2d4681a0c3e7f5b9d2a4c6e8f0a1b3d5c7e9
                    amendatoryMarkup: lost
                    nextCursor: >-
                      eyJ2IjoyLCJvIjoyOTkzMSwiaCI6ImI0ZTFhMDdjOTVkM2Y2MjgifQ.2_rL-kBijt3L90qgSkyk5g
                    hasMore: true
                    processingTimeMs: 598.7
                    creditsConsumed: 6
                    version: 1
                    isCurrentVersion: false
                unverifiedRead:
                  summary: >-
                    includeUnverified=true on a withheld law: the text is
                    served, flagged with `textReliability`, `reasonCode` and a
                    `notice` to show beside it
                  value:
                    citation: ACT No. 2
                    jurisdiction: la
                    session:
                      code: 2025R
                      label: 2025 Regular Session
                      type: regular
                      year: 2025
                    approvedDate: '2025-06-20'
                    approvedDateDerived: false
                    sourceUrl: https://www.legis.la.gov/legis/ViewDocument.aspx?d=1426048
                    sessionLawId: SSL_LA_2025R_G_C2
                    available: true
                    textStatus: withheld
                    withheldReason: >-
                      LA: struck (deleted) law is merged into the text as if
                      current while the record declares the markup preserved or
                      absent (audit 2026-10-03). Awaiting a re-run with strike
                      and underline recovery.
                    text: >-
                      ACT No. 2


                      AN ACT


                      To amend and reenact R.S. 47:287.732, relative to ...[the
                      text as held, abbreviated here]...
                    pageStart: 0
                    pageEnd: 29874
                    totalChars: 48213
                    totalPages: 2
                    pagePrice: 6
                    estimatedRemainingCredits: 6
                    textSha256: >-
                      7d21c5f08a3b94e6d1f0275ac8b3e94f62d0a17b5c8e3f9042a6d1b7e5c30f84
                    amendatoryMarkup: absent
                    nextCursor: >-
                      eyJ2IjoyLCJvIjoyOTg3NCwiaCI6IjdkMjFjNWYwOGEzYjk0ZTYifQ.7QQeKQEilQrbC8xVr_3SQw
                    hasMore: true
                    version: 1
                    isCurrentVersion: true
                    textReliability: known_issue
                    reasonCode: struck_text_merged
                    notice: >-
                      Deleted (struck) law is merged into this text as if it
                      were current. Read the printed act before relying on any
                      passage.
                    processingTimeMs: 244.6
                    creditsConsumed: 6
                unverifiedRefused:
                  summary: >-
                    includeUnverified=true on a law whose text failed our own
                    validation: never served, free, `available` false with the
                    `reasonCode`
                  value:
                    citation: ACT No. 3
                    jurisdiction: la
                    session:
                      code: 2025R
                      label: 2025 Regular Session
                      type: regular
                      year: 2025
                    approvedDate: '2025-06-20'
                    approvedDateDerived: false
                    sourceUrl: https://www.legis.la.gov/legis/ViewDocument.aspx?d=1426048
                    sessionLawId: SSL_LA_2025R_G_C3
                    available: false
                    reason: withheld
                    textStatus: withheld
                    withheldReason: >-
                      LA: loader validation failed; the text is held and not
                      served.
                    pagePrice: 0
                    amendatoryMarkup: absent
                    hasMore: false
                    version: 1
                    isCurrentVersion: true
                    reasonCode: validation_failed
                    processingTimeMs: 39.8
                    creditsConsumed: 0
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-RateLimit-Limit-Day:
              $ref: '#/components/headers/X-RateLimit-Limit-Day'
            X-RateLimit-Remaining-Day:
              $ref: '#/components/headers/X-RateLimit-Remaining-Day'
            X-RateLimit-Limit-Hour:
              $ref: '#/components/headers/X-RateLimit-Limit-Hour'
            X-RateLimit-Remaining-Hour:
              $ref: '#/components/headers/X-RateLimit-Remaining-Hour'
            X-RateLimit-Reset-Day:
              $ref: '#/components/headers/X-RateLimit-Reset-Day'
            X-RateLimit-Scope:
              $ref: '#/components/headers/X-RateLimit-Scope'
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '401':
          description: Missing, invalid or revoked API key. Not charged.
          content:
            application/json:
              example:
                detail: Invalid or expired API key
              schema:
                $ref: '#/components/schemas/ApiDetailError'
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-RateLimit-Limit-Day:
              $ref: '#/components/headers/X-RateLimit-Limit-Day'
            X-RateLimit-Remaining-Day:
              $ref: '#/components/headers/X-RateLimit-Remaining-Day'
            X-RateLimit-Limit-Hour:
              $ref: '#/components/headers/X-RateLimit-Limit-Hour'
            X-RateLimit-Remaining-Hour:
              $ref: '#/components/headers/X-RateLimit-Remaining-Hour'
            X-RateLimit-Reset-Day:
              $ref: '#/components/headers/X-RateLimit-Reset-Day'
            X-RateLimit-Scope:
              $ref: '#/components/headers/X-RateLimit-Scope'
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '402':
          description: >-
            Insufficient credits for this call. Nothing was done and nothing was
            charged. Read your balance, free, at `GET /credits/balance`.
          content:
            application/json:
              example:
                detail: Insufficient credits
              schema:
                $ref: '#/components/schemas/ApiDetailError'
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-RateLimit-Limit-Day:
              $ref: '#/components/headers/X-RateLimit-Limit-Day'
            X-RateLimit-Remaining-Day:
              $ref: '#/components/headers/X-RateLimit-Remaining-Day'
            X-RateLimit-Limit-Hour:
              $ref: '#/components/headers/X-RateLimit-Limit-Hour'
            X-RateLimit-Remaining-Hour:
              $ref: '#/components/headers/X-RateLimit-Remaining-Hour'
            X-RateLimit-Reset-Day:
              $ref: '#/components/headers/X-RateLimit-Reset-Day'
            X-RateLimit-Scope:
              $ref: '#/components/headers/X-RateLimit-Scope'
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '403':
          description: The API key lacks the `research:read` scope. Not charged.
          content:
            application/json:
              example:
                detail: Insufficient permissions for this operation
              schema:
                $ref: '#/components/schemas/ApiDetailError'
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-RateLimit-Limit-Day:
              $ref: '#/components/headers/X-RateLimit-Limit-Day'
            X-RateLimit-Remaining-Day:
              $ref: '#/components/headers/X-RateLimit-Remaining-Day'
            X-RateLimit-Limit-Hour:
              $ref: '#/components/headers/X-RateLimit-Limit-Hour'
            X-RateLimit-Remaining-Hour:
              $ref: '#/components/headers/X-RateLimit-Remaining-Hour'
            X-RateLimit-Reset-Day:
              $ref: '#/components/headers/X-RateLimit-Reset-Day'
            X-RateLimit-Scope:
              $ref: '#/components/headers/X-RateLimit-Scope'
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '404':
          description: >-
            Unknown id, a federal act, or an endpoint name where the id goes.
            `reason` says which. Never charged.
          content:
            application/json:
              examples:
                not_in_registry:
                  summary: No law carries this id
                  value:
                    detail: >-
                      Session law not found. No law in the registry carries this
                      id. Take ids from a /us/session-laws/list result. This
                      route takes ids only, not citations: GET
                      /us/session-laws/{sessionLawId} accepts a citation and
                      returns the id to send here.
                    sessionLawId: SSL_MN_1801R_G_Y1801_C9999
                    reason: not_in_registry
                    didYouMean: []
                wrong_case:
                  summary: The id exists in another letter case (never served for you)
                  value:
                    detail: >-
                      Session law not found. Ids are case-sensitive and this one
                      exists in a different case; see didYouMean.
                    sessionLawId: ssl_mn_2025r_g_y2025_c1
                    reason: wrong_case
                    didYouMean:
                      - SSL_MN_2025R_G_Y2025_C1
                federal_session_law:
                  summary: >-
                    A federal act: served by /us/statutes/section, refused
                    before any charge
                  value:
                    detail: >-
                      Session law not found. This endpoint covers STATE session
                      laws; federal session laws (the Statutes at Large) are
                      served by GET /us/statutes/section/{actId}. A federal id
                      (`SAL_...`) is not charged; a federal citation typed in
                      its place keeps the /us/statutes/resolve price, like any
                      unresolved citation.
                    sessionLawId: SAL_PL118-5
                    reason: federal_session_law
                    didYouMean: []
                missing_session_law_id:
                  summary: >-
                    An endpoint name where the id goes, refused before any
                    charge
                  value:
                    detail: >-
                      Session law not found. The URL has no session-law id in
                      it: the segment where the id goes names an endpoint, for
                      example /us/session-laws/{sessionLawId}/body. Nothing was
                      charged.
                    sessionLawId: body
                    reason: missing_session_law_id
                    didYouMean: []
                session_not_fully_collected:
                  summary: >-
                    Nothing matched, and the session is only partly collected:
                    the law may exist (nothing is charged, the resolve price
                    included)
                  value:
                    detail: >-
                      Session law not found. Nothing matched, and the session
                      this points into is only partly collected, so the law may
                      exist and not be held yet. `sessionCoverage` says how much
                      of the session we hold. Nothing was charged: a miss in a
                      partly collected session is never billed.
                    sessionLawId: SSL_DE_2025R_G_C3
                    reason: session_not_fully_collected
                    didYouMean: []
                    sessionCoverage:
                      code: 2025R
                      label: 153rd General Assembly
                      type: regular
                      year: 2025
                      status: partial
                      servedCount: 43
                      withheldCount: 0
                      notHeldCount: 0
                      registryCount: 43
                      collectedCount: 43
                      denominator:
                        kind: complete_listing
                        value: 296
                        derivation: >-
                          The publisher's complete listing of this session names
                          296 measures. We hold 43 of them; the rest are not yet
                          collected.
                      openGaps: 253
                      numberingHoles: 0
                      denominatorStale: false
              schema:
                $ref: '#/components/schemas/SessionLawNotFoundError'
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-RateLimit-Limit-Day:
              $ref: '#/components/headers/X-RateLimit-Limit-Day'
            X-RateLimit-Remaining-Day:
              $ref: '#/components/headers/X-RateLimit-Remaining-Day'
            X-RateLimit-Limit-Hour:
              $ref: '#/components/headers/X-RateLimit-Limit-Hour'
            X-RateLimit-Remaining-Hour:
              $ref: '#/components/headers/X-RateLimit-Remaining-Hour'
            X-RateLimit-Reset-Day:
              $ref: '#/components/headers/X-RateLimit-Reset-Day'
            X-RateLimit-Scope:
              $ref: '#/components/headers/X-RateLimit-Scope'
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '409':
          description: >-
            The `cursor` was cut from an earlier version of this law's text, or
            the `expectTextSha256` you sent is not its hash: the text has since
            been re-collected. Not charged. Start again without `cursor`.
            Idempotency conflict. `idempotency_in_progress`: the original
            request with this key is still running (retry after `Retry-After`).
            `idempotency_replay_unavailable`: it completed but its response was
            not kept (too large, or the account's data retention setting), so it
            cannot be replayed; nothing is charged again, so check the credit
            balance instead of retrying. Read the top-level `code`; `detail` is
            the message string, as on every other error. A replayed response
            reports `creditsConsumed: 0`.
          content:
            application/json:
              examples:
                staleCursor:
                  summary: A `cursor` from before the text was re-collected
                  value:
                    detail: >-
                      This cursor belongs to an earlier version of the text.
                      Start again without `cursor`.
                cursorOfAnotherLaw:
                  summary: A `cursor` issued for a different law
                  value:
                    detail: >-
                      This cursor was issued for a different law. A `cursor`
                      pages one law's text: start this law again without
                      `cursor`.
                staleHash:
                  summary: An `expectTextSha256` that is no longer the text's hash
                  value:
                    detail: >-
                      The text of this law no longer matches `expectTextSha256`
                      (it was re-collected). Read `textSha256` from the law and
                      start again.
              schema:
                $ref: '#/components/schemas/ApiDetailError'
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-RateLimit-Limit-Day:
              $ref: '#/components/headers/X-RateLimit-Limit-Day'
            X-RateLimit-Remaining-Day:
              $ref: '#/components/headers/X-RateLimit-Remaining-Day'
            X-RateLimit-Limit-Hour:
              $ref: '#/components/headers/X-RateLimit-Limit-Hour'
            X-RateLimit-Remaining-Hour:
              $ref: '#/components/headers/X-RateLimit-Remaining-Hour'
            X-RateLimit-Reset-Day:
              $ref: '#/components/headers/X-RateLimit-Reset-Day'
            X-RateLimit-Scope:
              $ref: '#/components/headers/X-RateLimit-Scope'
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '422':
          description: >-
            A parameter failed validation: a `cursor` we did not issue, `cursor`
            sent with `startChar`, or a malformed `startChar` or
            `expectTextSha256`. Never charged. `errors[].loc` names the
            parameter exactly as you send it. `idempotency_key_reused`: the
            `Idempotency-Key` was already used with a different request (another
            body, path or method). Not charged.
          content:
            application/json:
              examples:
                badCursor:
                  summary: A `cursor` this API did not issue
                  value:
                    detail: '`cursor` is not one this API issued.'
                    reason: invalid_cursor
                cursorExpired:
                  summary: A `cursor` from before the cursor format changed
                  value:
                    detail: >-
                      `cursor` is from an earlier version of this API and has
                      expired. Restart without `cursor`.
                    reason: cursor_expired
                cursorPastEnd:
                  summary: >-
                    A `cursor` at or beyond the end of the text (never issued by
                    this API)
                  value:
                    detail: >-
                      `cursor` points past the end of this law's text. A final
                      page has no `nextCursor`: restart without `cursor`.
                    reason: cursor_past_end
                cursorAndStartChar:
                  summary: >-
                    `cursor` and `startChar` together: a cursor already says
                    where the page starts
                  value:
                    detail: >-
                      Send either `cursor` or `startChar`, not both: a cursor
                      already says where the page starts.
                startCharPastEnd:
                  summary: '`startChar=400000` on a text of 310454 characters (refunded)'
                  value:
                    detail: >-
                      `startChar` (400000) is at or beyond the end of this law's
                      text, which is 310454 characters long. Nothing was
                      charged.
                startCharNegative:
                  summary: '`startChar=-1`'
                  value:
                    detail: Invalid request parameters
                    errors:
                      - loc:
                          - query
                          - startChar
                        msg: Input should be greater than or equal to 0
                        type: greater_than_equal
                badExpectTextSha256:
                  summary: '`expectTextSha256=abc`: 16 to 64 lowercase hex characters'
                  value:
                    detail: Invalid request parameters
                    errors:
                      - loc:
                          - query
                          - expectTextSha256
                        msg: String should match pattern '^[0-9a-f]{16,64}$'
                        type: string_pattern_mismatch
              schema:
                $ref: '#/components/schemas/ApiDetailError'
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-RateLimit-Limit-Day:
              $ref: '#/components/headers/X-RateLimit-Limit-Day'
            X-RateLimit-Remaining-Day:
              $ref: '#/components/headers/X-RateLimit-Remaining-Day'
            X-RateLimit-Limit-Hour:
              $ref: '#/components/headers/X-RateLimit-Limit-Hour'
            X-RateLimit-Remaining-Hour:
              $ref: '#/components/headers/X-RateLimit-Remaining-Hour'
            X-RateLimit-Reset-Day:
              $ref: '#/components/headers/X-RateLimit-Reset-Day'
            X-RateLimit-Scope:
              $ref: '#/components/headers/X-RateLimit-Scope'
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '429':
          description: >-
            Rate limit exceeded for your key. Not charged. Wait `Retry-After`
            seconds.
          headers:
            Retry-After:
              $ref: '#/components/headers/Retry-After'
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-RateLimit-Limit-Day:
              $ref: '#/components/headers/X-RateLimit-Limit-Day'
            X-RateLimit-Remaining-Day:
              $ref: '#/components/headers/X-RateLimit-Remaining-Day'
            X-RateLimit-Limit-Hour:
              $ref: '#/components/headers/X-RateLimit-Limit-Hour'
            X-RateLimit-Remaining-Hour:
              $ref: '#/components/headers/X-RateLimit-Remaining-Hour'
            X-RateLimit-Reset-Day:
              $ref: '#/components/headers/X-RateLimit-Reset-Day'
            X-RateLimit-Scope:
              $ref: '#/components/headers/X-RateLimit-Scope'
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
          content:
            application/json:
              example:
                detail: Rate limit exceeded. Try again in 12 seconds.
              schema:
                $ref: '#/components/schemas/ApiDetailError'
        '500':
          description: An unexpected failure on our side. The charge is refunded.
          content:
            application/json:
              example:
                detail: Internal server error
              schema:
                $ref: '#/components/schemas/ApiDetailError'
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-RateLimit-Limit-Day:
              $ref: '#/components/headers/X-RateLimit-Limit-Day'
            X-RateLimit-Remaining-Day:
              $ref: '#/components/headers/X-RateLimit-Remaining-Day'
            X-RateLimit-Limit-Hour:
              $ref: '#/components/headers/X-RateLimit-Limit-Hour'
            X-RateLimit-Remaining-Hour:
              $ref: '#/components/headers/X-RateLimit-Remaining-Hour'
            X-RateLimit-Reset-Day:
              $ref: '#/components/headers/X-RateLimit-Reset-Day'
            X-RateLimit-Scope:
              $ref: '#/components/headers/X-RateLimit-Scope'
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
        '503':
          description: >-
            The session-laws database is temporarily unavailable. The charge is
            refunded; retry.
          content:
            application/json:
              example:
                detail: >-
                  The US session-laws database is temporarily unavailable.
                  Please retry.
              schema:
                $ref: '#/components/schemas/ApiDetailError'
          headers:
            X-RateLimit-Limit:
              $ref: '#/components/headers/X-RateLimit-Limit'
            X-RateLimit-Remaining:
              $ref: '#/components/headers/X-RateLimit-Remaining'
            X-RateLimit-Reset:
              $ref: '#/components/headers/X-RateLimit-Reset'
            X-RateLimit-Limit-Day:
              $ref: '#/components/headers/X-RateLimit-Limit-Day'
            X-RateLimit-Remaining-Day:
              $ref: '#/components/headers/X-RateLimit-Remaining-Day'
            X-RateLimit-Limit-Hour:
              $ref: '#/components/headers/X-RateLimit-Limit-Hour'
            X-RateLimit-Remaining-Hour:
              $ref: '#/components/headers/X-RateLimit-Remaining-Hour'
            X-RateLimit-Reset-Day:
              $ref: '#/components/headers/X-RateLimit-Reset-Day'
            X-RateLimit-Scope:
              $ref: '#/components/headers/X-RateLimit-Scope'
            X-Request-ID:
              $ref: '#/components/headers/X-Request-ID'
      externalDocs:
        description: Session laws guide
        url: https://www.vaquill.ai/docs/api-guide/session-laws
components:
  schemas:
    SessionLawBodyResponse:
      properties:
        processingTimeMs:
          type: number
          title: Processingtimems
          description: >-
            Server-side time for this request in milliseconds, excluding network
            transit. Not billed on.
          default: 0
          examples:
            - 747.5
        creditsConsumed:
          type: number
          title: Creditsconsumed
          description: >-
            Credits actually charged for this call, never the list price. It
            includes the `/us/statutes/resolve` fee when a citation was sent
            where an id goes. 0 when the call was not charged or was refunded (a
            body that answers `available: false`).
          default: 0
          examples:
            - 2
        sessionLawId:
          type: string
          title: Sessionlawid
          description: The law this page belongs to.
          examples:
            - SSL_MN_2025S1_G_Y2025_C1
        citation:
          type: string
          title: Citation
          description: >-
            The act's citation as its publisher prints it, the same as
            `citation` on `GET /us/session-laws/{sessionLawId}`. Carried here so
            a page is attributable on its own, with no second call.
          examples:
            - CHAPTER 1--S.F.No. 3
        jurisdiction:
          type: string
          title: Jurisdiction
          description: Lowercase two-letter code of the state, `dc` or `pr`.
          examples:
            - mn
        session:
          $ref: '#/components/schemas/SessionLawSession'
          description: The legislative session the law was enacted in.
        approvedDate:
          anyOf:
            - type: string
              format: date
            - type: 'null'
          title: Approveddate
          description: >-
            Date the governor approved the act, ISO 8601, as on `GET
            /us/session-laws/{sessionLawId}`: never an effective date. Null when
            none is held. See `approvedDateDerived`.
          examples:
            - '2025-06-14'
        approvedDateDerived:
          type: boolean
          title: Approveddatederived
          description: >-
            True only when `approvedDate` was filled from the publisher's dated
            signature label rather than held as the approval date. See the same
            field on `GET /us/session-laws/{sessionLawId}`.
          default: false
          examples:
            - false
        sourceUrl:
          anyOf:
            - type: string
            - type: 'null'
          title: Sourceurl
          description: >-
            The official page or file this text was collected from, on a
            government publisher's host. Present on EVERY outcome, a withheld or
            not-held law included, so a reader is never at a dead end: where we
            do not serve the text, this is where to read it. Null only when we
            hold no government text source for the law.
          examples:
            - https://www.revisor.mn.gov/laws/2025/1/Session+Law/Chapter/1/
        officialUrl:
          anyOf:
            - type: string
            - type: 'null'
          title: Officialurl
          description: >-
            The publisher's page for this act (never a Vaquill URL): the
            legislature's page for the bill where it keeps one, else
            `sourceUrl`. See the same field on `GET
            /us/session-laws/{sessionLawId}`.
          examples:
            - https://www.nysenate.gov/legislation/bills/2025/A414
        available:
          type: boolean
          title: Available
          description: >-
            False when we do not serve this law's text; `reason` says why. A
            page with `available: false` is not charged.
          examples:
            - true
        reason:
          anyOf:
            - type: string
            - type: 'null'
          title: Reason
          description: >-
            Why `available` is false: `not_held`, `withheld`, `pending` or
            `empty_text`. Null when the text is served.
          examples:
            - withheld
            - null
        textStatus:
          type: string
          enum:
            - held
            - withheld
            - not_held
            - pending
          title: Textstatus
          description: >-
            Whether we serve this law's text. `held`: the text is served by
            `/us/session-laws/{sessionLawId}/body`. `withheld`: we hold the text
            but a measured defect keeps it from being served, and
            `withheldReason` says what. `not_held`: we know the act exists and
            do not hold its text. `pending`: collected and not yet verified.
          examples:
            - held
        withheldReason:
          anyOf:
            - type: string
            - type: 'null'
          title: Withheldreason
          description: >-
            Present only when `textStatus` is `withheld`: what is wrong with the
            text we hold. A plain sentence to show, not an enum to branch on.
          examples:
            - >-
              LA: struck (deleted) law is merged into the text as if current
              while the record declares the markup preserved or absent (audit
              2026-10-03). Awaiting a re-run with strike and underline recovery.
            - null
        text:
          anyOf:
            - type: string
            - type: 'null'
          title: Text
          description: >-
            This page of the act's text, exactly as printed, in reading order.
            Concatenating every page's `text` in order reproduces the whole
            text. Where `amendatoryMarkup` is `preserved`, struck and inserted
            language is in the text in the convention `markupConvention` names.
            Null when `available` is false.
          examples:
            - |-
              CHAPTER 1--S.F.No. 1552

              An act

              relating to agriculture; ...
        pageStart:
          anyOf:
            - type: integer
            - type: 'null'
          title: Pagestart
          description: >-
            Character offset in the full text where this page starts (0-based).
            Pages are contiguous: the next page's `pageStart` equals this page's
            `pageEnd`.
          examples:
            - 0
        pageEnd:
          anyOf:
            - type: integer
            - type: 'null'
          title: Pageend
          description: >-
            Character offset just past this page. A page is about 30,000
            characters, cut back to a paragraph break where one is near, so the
            length varies.
          examples:
            - 29987
        totalChars:
          anyOf:
            - type: integer
            - type: 'null'
          title: Totalchars
          description: >-
            Length of the whole text in characters. This page is the last when
            `pageEnd` equals it.
          examples:
            - 310454
        totalPages:
          anyOf:
            - type: integer
            - type: 'null'
          title: Totalpages
          description: >-
            The most pages the whole text can take: a page holds up to the page
            size but is cut back to a paragraph break, so every page but the
            last is counted at its shortest size. A long act usually takes fewer
            pages and never more. Null when no text is served.
          examples:
            - 11
        pagePrice:
          type: integer
          title: Pageprice
          description: >-
            Credits charged for the page in this response, the same as
            `creditsConsumed` on this route: the price of one page when a page
            was served, 0 when none was (`available` is false). Each further
            page costs the same.
          default: 0
          examples:
            - 6
        estimatedRemainingCredits:
          anyOf:
            - type: integer
            - type: 'null'
          title: Estimatedremainingcredits
          description: >-
            The most credits to read the rest of the text from `pageEnd`: the
            most pages still to come (counted at the shortest size a page can be
            cut back to) times the price of a page. 0 on the last page. Null
            when no text is served. An upper bound that is never below what
            reading the rest costs. Reading a whole law costs
            `estimatedBodyPages` times the price of one body page (6 credits per
            page on `GET /us/session-laws/{sessionLawId}/body`); most acts are a
            page or two.
          examples:
            - 60
        textSha256:
          anyOf:
            - type: string
            - type: 'null'
          title: Textsha256
          description: >-
            SHA-256 (hex) of the full text of this law. It changes only when the
            text does, so it is the cheap way to tell whether a copy you hold is
            current. Body pages carry the same value.
          examples:
            - 02693d5b55d4709bdd36fdccee4a9737d2655a3988a90daeb6b7c486ce50260b
        amendatoryMarkup:
          anyOf:
            - type: string
            - type: 'null'
          title: Amendatorymarkup
          description: >-
            Whether the language an amending act strikes and inserts survives in
            the text. `preserved`: it is in `text`, in the convention
            `markupConvention` names. `lost`: the publisher printed it and our
            text does not keep it, so deleted words can read as law: check the
            source before quoting. `absent`: the act carries no such markup that
            we found. `not_applicable`: there is no text to carry it.
          examples:
            - preserved
        markupConvention:
          anyOf:
            - type: string
            - type: 'null'
          title: Markupconvention
          description: >-
            How preserved markup is written, set only when `amendatoryMarkup` is
            `preserved`. `wdiff`: deleted language is `[-like this-]` and
            inserted language `{+like this+}`. `publisher_literal`: the
            publisher's own words are left as printed (Minnesota prints `new
            text begin` / `new text end` and `deleted text begin` / `deleted
            text end` markers). `mixed`: both in one text.
          examples:
            - publisher_literal
            - null
        nextCursor:
          anyOf:
            - type: string
            - type: 'null'
          title: Nextcursor
          description: >-
            Opaque cursor for the next page: send it as `cursor` on the same
            path. Null on the last page. It is tied to this exact text, so a
            cursor from before the text was re-collected is a 409.
          examples:
            - eyJ2IjoxLCJvIjoyOTk4NywiaCI6IjAyNjkzZDViNTVkNDcwOWIifQ
        hasMore:
          type: boolean
          title: Hasmore
          description: >-
            True when more pages follow; fetch them with `nextCursor`. Each page
            is charged.
          default: false
          examples:
            - true
        version:
          anyOf:
            - type: integer
            - type: 'null'
          title: Version
          description: >-
            Which version of the act this page belongs to, the `version` of `GET
            /us/session-laws/{sessionLawId}/versions`. Present only when you
            sent `version` or `includeUnverified`; absent otherwise (the current
            version).
          examples:
            - 2
        isCurrentVersion:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Iscurrentversion
          description: >-
            True when `version` is the version `GET
            /us/session-laws/{sessionLawId}` serves now. Present with `version`.
          examples:
            - false
        textReliability:
          anyOf:
            - type: string
              enum:
                - verified
                - unverified
                - known_issue
            - type: 'null'
          title: Textreliability
          description: >-
            How far to trust this text. Present when you sent
            `includeUnverified=true`, and on every read whose text is not
            `verified`. `verified`: the text passed our strike-through check.
            `unverified`: a check has not been completed, so the text MAY show
            deleted or vetoed law as if enacted. `known_issue`: we have evidence
            it does. A served law can be any of the three and its text is served
            either way. Branch on `reasonCode`, show `notice`.
          examples:
            - unverified
        reasonCode:
          anyOf:
            - type: string
            - type: 'null'
          title: Reasoncode
          description: >-
            Present when the text is not `verified`, or when
            `includeUnverified=true` refuses it: a stable token, one of
            `markup_unverified`, `strike_unchecked`,
            `struck_text_shown_as_current`, `struck_text_merged`,
            `veto_unchecked`, `licence_unconfirmed`, `markup_contradicted`,
            `struck_text_evidenced`, `markup_lost`, `strike_unconfirmed` (the
            text is served with a flag) or `validation_failed`,
            `session_unresolved`, `collector_unaudited`, `licence_barred`,
            `unclassified` (the text is not served). The sentence in
            `withheldReason` is for people; branch on this.
          examples:
            - strike_unchecked
        notice:
          anyOf:
            - type: string
            - type: 'null'
          title: Notice
          description: >-
            One plain sentence saying what is uncertain about this text and what
            to do about it. Present exactly when `textReliability` is
            `unverified` or `known_issue`. Show it beside the text.
          examples:
            - >-
              Deleted (struck) language in the source has not yet been checked
              against this text, so it may read as enacted law. Do not rely on
              this text without checking the printed act.
      type: object
      required:
        - sessionLawId
        - citation
        - jurisdiction
        - session
        - available
        - textStatus
      title: SessionLawBodyResponse
      description: Response for `GET /us/session-laws/{sessionLawId}/body`.
    ApiDetailError:
      properties:
        detail:
          type: string
          title: Detail
          description: >-
            Human-readable reason, safe to surface to an end user. Branch on the
            HTTP status rather than on this string: the wording is not part of
            the contract and may be reworded, but 401 (bad key), 402 (out of
            credits), 403 (missing scope), 404 (no such resource) and 429 (rate
            limited) are stable.
          examples:
            - Insufficient API credits.
        errors:
          anyOf:
            - items:
                $ref: '#/components/schemas/ApiFieldError'
              type: array
            - type: 'null'
          title: Errors
          description: 'Present on 422 only: every field that failed validation.'
        code:
          anyOf:
            - type: string
            - type: 'null'
          title: Code
          description: >-
            Stable machine code for the failure. Branch on this, not on
            `detail`. The set is open: tolerate values you do not know. Known
            values: authentication_required, invalid_api_key, api_key_expired,
            permission_denied, insufficient_scope, insufficient_credits,
            payment_required, rate_limited, quota_exceeded, daily_cap_exceeded,
            bad_request, validation_error, method_not_allowed,
            payload_too_large, unsupported_media_type, invalid_query,
            invalid_citation_input, section_not_found, resource_not_found,
            idempotency_key_reused, idempotency_in_progress,
            idempotency_replay_unavailable, upstream_timeout,
            service_unavailable, internal_error, conflict.
          examples:
            - insufficient_credits
          x-known-values:
            - authentication_required
            - invalid_api_key
            - api_key_expired
            - permission_denied
            - insufficient_scope
            - insufficient_credits
            - payment_required
            - rate_limited
            - quota_exceeded
            - daily_cap_exceeded
            - bad_request
            - validation_error
            - method_not_allowed
            - payload_too_large
            - unsupported_media_type
            - invalid_query
            - invalid_citation_input
            - section_not_found
            - resource_not_found
            - idempotency_key_reused
            - idempotency_in_progress
            - idempotency_replay_unavailable
            - upstream_timeout
            - service_unavailable
            - internal_error
            - conflict
        type:
          anyOf:
            - type: string
            - type: 'null'
          title: Type
          description: >-
            URL naming the error kind,
            `https://www.vaquill.ai/docs/errors/{code}`.
          examples:
            - https://www.vaquill.ai/docs/errors/insufficient_credits
        title:
          anyOf:
            - type: string
            - type: 'null'
          title: Title
          description: Short fixed English title for `code`.
          examples:
            - Insufficient credits
        status:
          anyOf:
            - type: integer
            - type: 'null'
          title: Status
          description: Echo of the HTTP status code.
          examples:
            - 402
        requestId:
          anyOf:
            - type: string
            - type: 'null'
          title: Requestid
          description: Equals the `X-Request-ID` response header. Quote it to support.
          examples:
            - 8d32789e-7b27-44f7-9523-424596e7a929
        retryable:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Retryable
          description: True only when repeating the same request is safe and may succeed.
          examples:
            - false
        retryAfterSeconds:
          anyOf:
            - type: integer
            - type: 'null'
          title: Retryafterseconds
          description: 'On 429 and 503 when `Retry-After` is set: the same value in seconds.'
          examples:
            - 30
        actId:
          anyOf:
            - type: string
            - type: 'null'
          title: Actid
          description: 'Section routes only, on a miss: the identifier that matched nothing.'
          examples:
            - UNKNOWN_99999
        reason:
          anyOf:
            - type: string
            - type: 'null'
          title: Reason
          description: >-
            Section routes only, on a miss: why nothing matched, for example
            `unsupported_jurisdiction` or `not_in_registry`. The set is open.
          examples:
            - not_in_registry
        didYouMean:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Didyoumean
          description: 'Section routes only, on a miss: identifiers worth trying instead.'
        sessionLawId:
          anyOf:
            - type: string
            - type: 'null'
          title: Sessionlawid
          description: >-
            Session-law routes only, on a miss: the id or citation that matched
            nothing.
          examples:
            - Pub. L. 117-58
        defaultSessionLawId:
          anyOf:
            - type: string
            - type: 'null'
          title: Defaultsessionlawid
          description: >-
            Session-law routes only, on an `ambiguous_citation` miss: the
            conventional reading, which is NOT chosen for you. `didYouMean`
            lists every candidate.
          examples:
            - us1_ca_2019_ch_123
        candidateCount:
          anyOf:
            - type: integer
            - type: 'null'
          title: Candidatecount
          description: 'Session-law routes only: how many laws the citation names in all.'
          examples:
            - 3
        truncated:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Truncated
          description: >-
            Session-law routes only: true when `didYouMean` lists fewer laws
            than `candidateCount`, so the list is not complete.
          examples:
            - false
        jurisdictions:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Jurisdictions
          description: >-
            Session-law routes only, on a `needs_jurisdiction` miss: every state
            where the citation exists. Name one in the citation, or pass
            `state`.
        sessionCoverage:
          anyOf:
            - additionalProperties: true
              type: object
            - type: 'null'
          title: Sessioncoverage
          description: >-
            Session-law routes only, on a `session_not_fully_collected` miss:
            how much of the session we hold.
        creditsRequired:
          anyOf:
            - type: integer
            - type: 'null'
          title: Creditsrequired
          description: '402 only, when known: the credits this call needed.'
          examples:
            - 5
        creditsAvailable:
          anyOf:
            - type: integer
            - type: 'null'
          title: Creditsavailable
          description: '402 only, when known: the credits you can spend right now.'
          examples:
            - 2
        topUpHint:
          anyOf:
            - type: string
            - type: 'null'
          title: Topuphint
          description: '402 only, when known: where to add credits.'
          examples:
            - >-
              Add credits in the developer dashboard, then retry the same
              request.
      type: object
      required:
        - detail
      title: ApiDetailError
      description: >-
        Error envelope the API actually returns.


        Every error (400/401/402/403/404/405/422/429/5xx) carries a `detail`

        string, e.g. `{"detail": "Insufficient API credits."}`, on every mount
        of

        the API. A 422 adds `errors`, one entry per rejected field. Some 404s
        add

        endpoint-specific diagnosis beside `detail` (the statutes section routes

        add `actId`, `reason` and `didYouMean`); treat unknown keys as optional.
    SessionLawNotFoundError:
      properties:
        detail:
          type: string
          title: Detail
          description: >-
            Human-readable reason, safe to show a user. Branch on `reason`, not
            on this string: the wording can change.
          examples:
            - >-
              Session law not found. No law in the registry carries this id.
              Take ids from a /us/session-laws/list result, or send the citation
              in its place.
        sessionLawId:
          type: string
          title: Sessionlawid
          description: The identifier exactly as you sent it.
          examples:
            - SSL_MN_1801R_G_Y1801_C9999
        reason:
          type: string
          enum:
            - not_in_registry
            - wrong_case
            - unresolved_citation
            - ambiguous_citation
            - federal_session_law
            - missing_session_law_id
            - needs_jurisdiction
            - session_not_fully_collected
          title: Reason
          description: >-
            `not_in_registry`: no law carries this id. `wrong_case`: it exists
            in another letter case, see `didYouMean`. `unresolved_citation`: you
            sent a citation and no law carries it. `ambiguous_citation`: the
            citation names several laws, all in `didYouMean`, none chosen for
            you; `defaultSessionLawId` is the publisher's conventional reading
            when one is recorded. `federal_session_law`: federal acts are served
            by /us/statutes/section. `missing_session_law_id`: the URL names an
            endpoint where the id goes. `needs_jurisdiction`: the citation is in
            a form several states share and names none, so none was chosen for
            you; `jurisdictions` lists the states where it exists and
            `didYouMean` one law per state. `session_not_fully_collected`:
            nothing matched, and the session the id or citation points into is
            only partly collected, so the law may exist; `sessionCoverage` says
            how much of the session we hold. The route's price is never charged
            on a 404; a citation's resolution fee is kept on
            `unresolved_citation` and `needs_jurisdiction`, and refunded on
            `ambiguous_citation` (several laws carry it, none was chosen) and on
            `session_not_fully_collected`: a miss in a partly collected session
            is never charged.
          examples:
            - not_in_registry
        didYouMean:
          items:
            type: string
          type: array
          title: Didyoumean
          description: >-
            Real `sessionLawId`s the input points at: the one that exists in a
            different case, or every law an ambiguous citation names (at most
            20, the conventional reading first). Empty when nothing matched.
          examples:
            - - SSL_KY_2025R_G_Y2025_C100
              - SSL_MO_2025R_G_Y2025_BHB2
        defaultSessionLawId:
          anyOf:
            - type: string
            - type: 'null'
          title: Defaultsessionlawid
          description: >-
            On `ambiguous_citation`, the conventional reading when the registry
            records one, otherwise null. Informational: it is never served for
            you.
          examples:
            - null
        jurisdictions:
          anyOf:
            - items:
                type: string
              type: array
            - type: 'null'
          title: Jurisdictions
          description: >-
            On `needs_jurisdiction`, every state (lower-case postal code) where
            the citation you sent exists. Name one of them in the citation and
            send it again. Absent on every other reason.
          examples:
            - - il
              - mn
              - tx
        candidateCount:
          anyOf:
            - type: integer
            - type: 'null'
          title: Candidatecount
          description: >-
            On `ambiguous_citation` and `needs_jurisdiction`, how many laws the
            citation names in all. Compare it with `len(didYouMean)`: when it is
            larger, `truncated` is true and the list is a sample, not the full
            set.
          examples:
            - 22
        truncated:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Truncated
          description: >-
            True when `didYouMean` was capped (at most 20 ids) and
            `candidateCount` is larger than the list. Absent on reasons that
            carry no candidates.
          examples:
            - true
        sessionCoverage:
          anyOf:
            - $ref: '#/components/schemas/SessionLawSessionCoverage'
            - type: 'null'
          description: >-
            On `session_not_fully_collected`, the partly collected session the
            id or citation points into: how many laws we hold of how many it is
            expected to have (`denominator`), and how many are still open.
            Absent on every other reason. The same block is in
            `sessionLaws.sessions` on `GET /us/statutes/coverage`.
      type: object
      required:
        - detail
        - sessionLawId
        - reason
      title: SessionLawNotFoundError
      description: The 404 from `GET /us/session-laws/{sessionLawId}` and its `/body`.
    SessionLawSession:
      properties:
        code:
          type: string
          title: Code
          description: >-
            Session code, `{year}{type}{ordinal}`. `type` is `R` regular, `S`
            special, `X` extraordinary, `F` fiscal, `V` veto, `U` unknown. A
            regular session has no ordinal (`2025R`); a numbered special session
            carries it (`2025S1`, the first special session of 2025); a lettered
            one carries its letter (`2025SC`, Florida's Special Session C).
            `year` is the year the publisher numbers the session by, which for a
            period spanning two years is the first (District of Columbia Council
            Period 25 is `2023R`). Pass it as `session` to `GET
            /us/session-laws/list`.
          examples:
            - 2025R
            - 2025S1
        label:
          anyOf:
            - type: string
            - type: 'null'
          title: Label
          description: The session's canonical label, as the publisher names it.
          examples:
            - 2025 Regular Session
            - 2025 1st Special Session
        type:
          anyOf:
            - type: string
            - type: 'null'
          title: Type
          description: >-
            `regular`, `special`, `extraordinary`, `fiscal`, `veto` or
            `unknown`.
          examples:
            - regular
        year:
          anyOf:
            - type: integer
            - type: 'null'
          title: Year
          description: The year the session convened, the same year `code` starts with.
          examples:
            - 2025
      type: object
      required:
        - code
      title: SessionLawSession
      description: The legislative session a law was enacted in.
    ApiFieldError:
      properties:
        loc:
          items:
            anyOf:
              - type: string
              - type: integer
          type: array
          title: Loc
          description: >-
            Where the bad value is: `body`, `query` or `path`, then the
            parameter name exactly as you send it (camelCase), then list
            indexes. A bare `["body"]` means the body as a whole was not a JSON
            object.
          examples:
            - - body
              - query
        msg:
          type: string
          title: Msg
          description: What is wrong with the value, in plain English.
          examples:
            - Field required
        type:
          type: string
          title: Type
          description: >-
            Machine-readable error kind, e.g. `missing`, `literal_error`,
            `json_invalid`.
          examples:
            - missing
      type: object
      required:
        - loc
        - msg
        - type
      title: ApiFieldError
      description: One rejected field in a 422 response.
    SessionLawSessionCoverage:
      properties:
        code:
          type: string
          title: Code
          description: Session code, for example `2025R`.
          examples:
            - 2025R
        label:
          anyOf:
            - type: string
            - type: 'null'
          title: Label
          description: The session's canonical label.
          examples:
            - 2025 Regular Session
        type:
          anyOf:
            - type: string
            - type: 'null'
          title: Type
          description: >-
            `regular`, `special`, `extraordinary`, `fiscal`, `veto` or
            `unknown`.
          examples:
            - regular
        year:
          anyOf:
            - type: integer
            - type: 'null'
          title: Year
          description: The year the session convened, the year `code` starts with.
          examples:
            - 2025
        status:
          type: string
          enum:
            - complete
            - partial
          title: Status
          description: >-
            `complete` when every law the publisher lists for the session is
            accounted for. Anything less is `partial`: a law missing from a
            partial session is not evidence that it does not exist, and asking
            for one by id or citation answers `session_not_fully_collected`,
            free of charge, rather than a plain not found.
          examples:
            - complete
        servedCount:
          type: integer
          minimum: 0
          title: Servedcount
          description: >-
            Laws from this session we serve: every one we answer for by id,
            citation or list, whether or not we hold its text (`notHeldCount` of
            them have none). Laws whose text is withheld are not counted here,
            they are `withheldCount`. `servedCount + withheldCount` is
            `registryCount`, less any law still being verified.
          examples:
            - 39
        withheldCount:
          type: integer
          minimum: 0
          title: Withheldcount
          description: >-
            Laws from this session we hold and list but whose text is withheld
            for a measured defect (`textStatus: withheld`). They are real laws:
            their records are served, their text is not.
          default: 0
          examples:
            - 0
        notHeldCount:
          type: integer
          minimum: 0
          title: Notheldcount
          description: >-
            Of the laws counted in `servedCount`, how many have no text held
            (`textStatus: not_held` or `pending`). A subset of `servedCount`,
            not an addition to it: do not add it to `servedCount` or
            `withheldCount`.
          default: 0
          examples:
            - 0
        registryCount:
          type: integer
          minimum: 0
          title: Registrycount
          description: >-
            Every law of this session in our registry, whether or not its text
            is held: `servedCount + withheldCount`. Any difference is a law
            still being verified, which is neither.
          default: 0
          examples:
            - 39
        collectedCount:
          type: integer
          minimum: 0
          title: Collectedcount
          description: >-
            Laws from this session whose text we have collected, served or
            withheld. Compare it with `denominator.value` to see how much of the
            session we hold.
          default: 0
          examples:
            - 39
        denominator:
          anyOf:
            - $ref: '#/components/schemas/SessionLawDenominator'
            - type: 'null'
          description: >-
            How many laws the session is expected to hold, and where that figure
            comes from. Null when it could not be read.
          examples:
            - derivation: >-
                The publisher's complete listing of this session names 296
                measures. We hold 43 of them; the rest are not yet collected.
              kind: complete_listing
              value: 296
        openGaps:
          type: integer
          minimum: 0
          title: Opengaps
          description: >-
            Laws the publisher lists for this session that we could not collect
            and have not yet. 0 on a `complete` session.
          default: 0
          examples:
            - 0
        numberingHoles:
          anyOf:
            - type: integer
              minimum: 0
            - type: 'null'
          title: Numberingholes
          description: >-
            Numbers inside the session's printed range that carry no law, which
            may never have been issued; null when not measured, and never
            counted in `openGaps`.
          examples:
            - 12
        denominatorStale:
          anyOf:
            - type: boolean
            - type: 'null'
          title: Denominatorstale
          description: >-
            True when our registry holds more laws than `denominator.value`, so
            the figure counts a narrower unit or is out of date and cannot
            measure what is missing; null when not assessed.
          examples:
            - false
        measuredAt:
          anyOf:
            - type: string
            - type: 'null'
          title: Measuredat
          description: When this session's coverage was last measured, ISO 8601 UTC.
          examples:
            - '2026-10-05T09:07:12+00:00'
      type: object
      required:
        - code
        - status
        - servedCount
      title: SessionLawSessionCoverage
      description: One legislative session's session-law coverage.
    SessionLawDenominator:
      properties:
        kind:
          type: string
          enum:
            - stated_count
            - complete_listing
            - max_number
            - feed_total
            - our_recount
            - registry_union
            - none
          title: Kind
          description: >-
            Where the total comes from. `stated_count`: the publisher states how
            many measures the session enacted. `complete_listing`: the
            publisher's own complete list of the session's acts, which we
            counted. `max_number`: the highest chapter number the publisher
            printed. `feed_total`: the total a publisher feed reports.
            `our_recount`: we counted the publisher's pages ourselves.
            `registry_union`: the measures we know of from several sources.
            `none`: no total is available, so completeness cannot be judged.
          examples:
            - complete_listing
        value:
          anyOf:
            - type: integer
              minimum: 0
            - type: 'null'
          title: Value
          description: >-
            The number of laws the session is expected to hold. Null when `kind`
            is `none`. Compare it with `registryCount` and `servedCount`.
          examples:
            - 296
        derivation:
          type: string
          title: Derivation
          description: >-
            One plain sentence saying what `value` counts and where it comes
            from. Written for customers: it never contains our internal audit or
            collection notes.
          examples:
            - The publisher's complete listing of this session names 296 acts.
      type: object
      required:
        - kind
        - derivation
      title: SessionLawDenominator
      description: >-
        How many laws a session is supposed to hold, and where that number comes
        from.
  headers:
    X-RateLimit-Limit:
      description: Requests allowed in the current per-minute window.
      schema:
        type: integer
    X-RateLimit-Remaining:
      description: Requests left in the current per-minute window.
      schema:
        type: integer
    X-RateLimit-Reset:
      description: Unix timestamp at which the per-minute window resets.
      schema:
        type: integer
    X-RateLimit-Limit-Day:
      description: Requests allowed per day (the slow-drip backstop).
      schema:
        type: integer
    X-RateLimit-Remaining-Day:
      description: Requests left in the daily window.
      schema:
        type: integer
    X-RateLimit-Limit-Hour:
      description: Requests allowed per hour.
      schema:
        type: integer
    X-RateLimit-Remaining-Hour:
      description: Requests left in the hourly window.
      schema:
        type: integer
    X-RateLimit-Reset-Day:
      description: Unix timestamp at which the daily window resets (next UTC midnight).
      schema:
        type: integer
    X-RateLimit-Scope:
      description: >-
        Which bucket the limits above describe: `key` (this API key's own
        allowance) or `ip` (the shared per-address ceiling, also used when the
        key did not validate). Absent on requests without an API key.
      schema:
        type: string
        enum:
          - key
          - ip
    X-Request-ID:
      description: Correlation id of this request. Quote it when contacting support.
      schema:
        type: string
    Retry-After:
      description: Seconds to wait before retrying.
      schema:
        type: integer
  securitySchemes:
    ApiKeyAuth:
      type: http
      scheme: bearer
      bearerFormat: vq_key_*
      description: >-
        API key issued from the developer dashboard. Pass as `Authorization:
        Bearer vq_key_...` (preferred).
    ApiKeyHeader:
      type: apiKey
      in: header
      name: X-API-Key
      description: >-
        The same API key as a bare header value: `X-API-Key: vq_key_...`.
        Equivalent to the Bearer form.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.