> ## 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.

# List every served version of a state session law

> Every version of one state session law that we served or adopted, newest first, and which of them is
current. A law's text can be corrected after we first serve it (a better extraction of the same
source, a re-collection), so the version you read yesterday may not be the one a plain call returns
today. This route lists each version with what identifies it (when we recorded it, its length, its
hash, how the text was taken) and how its text can be read. It carries no text: read one version with
`GET /us/session-laws/{sessionLawId}/body?version=N`.

**Cost**: 1 credit per call, however many versions the law has. A law with a single version
answers a list of one and is charged: "this law has never changed" is the answer you paid for. Reading
a version's text is a separate call at the body price (6 credits per page), the same as the
current text. A request that fails validation (422) is never charged.
A law that is not found (404) is never charged.
A failure on our side (500, 503) is refunded.

**Edge cases.** A law that is in the registry but has no version row (its current version is not set,
or it was withdrawn or merged into another law) answers `200` with `versions: []`, `count: 0` and a
`note`, and is not charged; it is never the 404 "no law carries this id". One answer lists at most
100 versions, newest first; `truncated: true` says older versions exist that it does not show.

**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. A federal id (`SAL_...`) is a 404
(`federal_session_law`), as on `/body`.

**What a version says.** `version` is the number to send as `version` on `/body`. Numbers can have
gaps: a version we recorded and never served or adopted is not listed. Exactly one listed version has
`isCurrent: true`, and `currentVersion` repeats its number: it is the text a plain `/body` call
serves. `recordedAt` dates our copy of the text, not the act (`approvedDate` on the law does that).
`totalChars` and `textSha256` identify the text: two versions with the same hash have the same text.
`citation`, `title` and `approvedDate` are as that version recorded them, so a correction that fixed
a title shows here.

| `textAccess` | Reading that version's text |
| --- | --- |
| `served` | A plain call to `/body?version=N`. |
| `includeUnverified` | The law is held back (`textStatus: withheld`); the text is readable only with `includeUnverified=true`, labelled by `textReliability` and `reasonCode` (it may show deleted or vetoed law as if it were enacted). |
| `none` | There is no text for this version, or the law's text may not be published (a licence that bars use, or text that failed our own validation). |

The law-level `textStatus`, `textReliability` and `reasonCode` are the same fields, with the same
meaning, as on `/body`. `textReliability` is omitted when no text of the law may be read, and
`reasonCode` when the law is served and verified. To check that nothing changed under you, compare
`textSha256` here with the one you read; the cursor rules for an older version are on `/body`.

**Example**

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

# then read the first version's text, one page at the body price
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"
```

```javascript
const id = "SSL_MN_2025S1_G_Y2025_C1";
const res = await fetch(`https://api.vaquill.ai/api/v1/us/session-laws/${encodeURIComponent(id)}/versions`, {
  headers: { Authorization: `Bearer ${process.env.VAQUILL_API_KEY}` },
});
const { versions, currentVersion } = await res.json();
const older = versions.filter((v) => !v.isCurrent && v.textAccess === "served");
```

**Related endpoints**

- `GET /us/session-laws/{sessionLawId}/body` reads the text of the current version, or of the one you
  name with `version`. It also takes `includeUnverified=true` for a law we hold back.
- `GET /us/session-laws/{sessionLawId}` is the law's record (dates, sources, code sections affected,
  whether its text is held); it always describes the current version.
- `GET /us/session-laws/changes` is the registry's change feed: a `corrected` entry there is how you
  learn that a copy of a law you hold may be stale, and this route is where you see what changed.
- `GET /us/statutes/coverage` says which sessions we hold and how complete each is, under each
  jurisdiction's `sessionLaws` block.
- Federal session laws (the Statutes at Large, `SAL_` ids) are not served here. Read them with
  `GET /us/statutes/section/{actId}`.

**Nulls.** A field of a version with no value (`citation`, `title`, `approvedDate`, `totalChars`,
`textSha256`, `textMethod`, `amendatoryMarkup`, `markupConvention`) is `null`. `textReliability` and
`reasonCode` on the law are absent, not null, when they do not apply. The examples here leave the
nulls out.

**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}/versions
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}/versions:
    get:
      tags:
        - US Session Laws
      summary: List every served version of a state session law
      description: >-
        Every version of one state session law that we served or adopted, newest
        first, and which of them is

        current. A law's text can be corrected after we first serve it (a better
        extraction of the same

        source, a re-collection), so the version you read yesterday may not be
        the one a plain call returns

        today. This route lists each version with what identifies it (when we
        recorded it, its length, its

        hash, how the text was taken) and how its text can be read. It carries
        no text: read one version with

        `GET /us/session-laws/{sessionLawId}/body?version=N`.


        **Cost**: 1 credit per call, however many versions the law has. A law
        with a single version

        answers a list of one and is charged: "this law has never changed" is
        the answer you paid for. Reading

        a version's text is a separate call at the body price (6 credits per
        page), the same as the

        current text. A request that fails validation (422) is never charged.

        A law that is not found (404) is never charged.

        A failure on our side (500, 503) is refunded.


        **Edge cases.** A law that is in the registry but has no version row
        (its current version is not set,

        or it was withdrawn or merged into another law) answers `200` with
        `versions: []`, `count: 0` and a

        `note`, and is not charged; it is never the 404 "no law carries this
        id". One answer lists at most

        100 versions, newest first; `truncated: true` says older versions exist
        that it does not show.


        **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. A
        federal id (`SAL_...`) is a 404

        (`federal_session_law`), as on `/body`.


        **What a version says.** `version` is the number to send as `version` on
        `/body`. Numbers can have

        gaps: a version we recorded and never served or adopted is not listed.
        Exactly one listed version has

        `isCurrent: true`, and `currentVersion` repeats its number: it is the
        text a plain `/body` call

        serves. `recordedAt` dates our copy of the text, not the act
        (`approvedDate` on the law does that).

        `totalChars` and `textSha256` identify the text: two versions with the
        same hash have the same text.

        `citation`, `title` and `approvedDate` are as that version recorded
        them, so a correction that fixed

        a title shows here.


        | `textAccess` | Reading that version's text |

        | --- | --- |

        | `served` | A plain call to `/body?version=N`. |

        | `includeUnverified` | The law is held back (`textStatus: withheld`);
        the text is readable only with `includeUnverified=true`, labelled by
        `textReliability` and `reasonCode` (it may show deleted or vetoed law as
        if it were enacted). |

        | `none` | There is no text for this version, or the law's text may not
        be published (a licence that bars use, or text that failed our own
        validation). |


        The law-level `textStatus`, `textReliability` and `reasonCode` are the
        same fields, with the same

        meaning, as on `/body`. `textReliability` is omitted when no text of the
        law may be read, and

        `reasonCode` when the law is served and verified. To check that nothing
        changed under you, compare

        `textSha256` here with the one you read; the cursor rules for an older
        version are on `/body`.


        **Example**


        ```bash

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

        # then read the first version's text, one page at the body price

        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"
        ```


        ```javascript

        const id = "SSL_MN_2025S1_G_Y2025_C1";

        const res = await
        fetch(`https://api.vaquill.ai/api/v1/us/session-laws/${encodeURIComponent(id)}/versions`,
        {
          headers: { Authorization: `Bearer ${process.env.VAQUILL_API_KEY}` },
        });

        const { versions, currentVersion } = await res.json();

        const older = versions.filter((v) => !v.isCurrent && v.textAccess ===
        "served");

        ```


        **Related endpoints**


        - `GET /us/session-laws/{sessionLawId}/body` reads the text of the
        current version, or of the one you
          name with `version`. It also takes `includeUnverified=true` for a law we hold back.
        - `GET /us/session-laws/{sessionLawId}` is the law's record (dates,
        sources, code sections affected,
          whether its text is held); it always describes the current version.
        - `GET /us/session-laws/changes` is the registry's change feed: a
        `corrected` entry there is how you
          learn that a copy of a law you hold may be stale, and this route is where you see what changed.
        - `GET /us/statutes/coverage` says which sessions we hold and how
        complete each is, under each
          jurisdiction's `sessionLaws` block.
        - Federal session laws (the Statutes at Large, `SAL_` ids) are not
        served here. Read them with
          `GET /us/statutes/section/{actId}`.

        **Nulls.** A field of a version with no value (`citation`, `title`,
        `approvedDate`, `totalChars`,

        `textSha256`, `textMethod`, `amendatoryMarkup`, `markupConvention`) is
        `null`. `textReliability` and

        `reasonCode` on the law are absent, not null, when they do not apply.
        The examples here leave the

        nulls out.


        **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_versions
      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: 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: >-
            The law's versions, newest first, exactly one of them current. A law
            with a single version answers a list of one, which is charged.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionLawVersionsResponse'
              examples:
                corrected:
                  summary: >-
                    A law whose text was re-collected: two versions, newest
                    first. Read the older one with `/body?version=1`
                  value:
                    sessionLawId: SSL_MN_2025S1_G_Y2025_C1
                    textStatus: held
                    textReliability: verified
                    versions:
                      - version: 2
                        isCurrent: true
                        recordedAt: '2026-10-13T09:04:11.120118+00:00'
                        citation: CHAPTER 1--S.F.No. 3
                        title: Environment and natural resources appropriations
                        approvedDate: '2025-06-14'
                        totalChars: 310454
                        textSha256: >-
                          02693d5b55d4709bdd36fdccee4a9737d2655a3988a90daeb6b7c486ce50260b
                        textMethod: html
                        amendatoryMarkup: preserved
                        markupConvention: publisher_literal
                        textAccess: served
                      - version: 1
                        isCurrent: false
                        recordedAt: '2026-10-05T09:04:11.120118+00:00'
                        citation: CHAPTER 1--S.F.No. 3
                        title: Environment and natural resources appropriations
                        approvedDate: '2025-06-14'
                        totalChars: 309876
                        textSha256: >-
                          b4e1a07c95d3f6280c1d7a3e5f9b2d4681a0c3e7f5b9d2a4c6e8f0a1b3d5c7e9
                        textMethod: pdf_text_layer
                        amendatoryMarkup: lost
                        textAccess: served
                    count: 2
                    currentVersion: 2
                    truncated: false
                    creditsConsumed: 1
                    processingTimeMs: 38.2
                singleVersion:
                  summary: 'A law that has never changed: a list of one, charged'
                  value:
                    sessionLawId: SSL_MN_2025R_G_Y2025_C1
                    textStatus: held
                    textReliability: verified
                    versions:
                      - version: 1
                        isCurrent: true
                        recordedAt: '2026-10-05T09:04:11.120118+00:00'
                        citation: CHAPTER 1--S.F.No. 1552
                        approvedDate: '2025-03-17'
                        totalChars: 5470
                        textSha256: >-
                          55c7a8d08647e41f87e23fc2016881a6583911a1d5cfa8687403442e9096451b
                        textMethod: html
                        amendatoryMarkup: preserved
                        markupConvention: publisher_literal
                        textAccess: served
                    count: 1
                    currentVersion: 1
                    truncated: false
                    creditsConsumed: 1
                    processingTimeMs: 21.5
                heldBack:
                  summary: >-
                    A law we hold back: its text is readable only with
                    `includeUnverified=true`, and `textReliability` and
                    `reasonCode` say how far to trust it
                  value:
                    sessionLawId: SSL_LA_2025R_G_C2
                    textStatus: withheld
                    textReliability: known_issue
                    reasonCode: struck_text_merged
                    versions:
                      - version: 1
                        isCurrent: true
                        recordedAt: '2026-10-05T09:04:11.120118+00:00'
                        citation: ACT No. 2
                        approvedDate: '2025-06-20'
                        totalChars: 48213
                        textSha256: >-
                          7d21c5f08a3b94e6d1f0275ac8b3e94f62d0a17b5c8e3f9042a6d1b7e5c30f84
                        textMethod: pdf_text_layer
                        amendatoryMarkup: absent
                        textAccess: includeUnverified
                    count: 1
                    currentVersion: 1
                    truncated: false
                    creditsConsumed: 1
                    processingTimeMs: 24.9
                notServed:
                  summary: >-
                    A law whose text may not be read at all (it failed our own
                    validation, or its licence bars use): `textAccess` is `none`
                    and no `textReliability` is given
                  value:
                    sessionLawId: SSL_LA_2025R_G_C3
                    textStatus: withheld
                    reasonCode: validation_failed
                    versions:
                      - version: 1
                        isCurrent: true
                        recordedAt: '2026-10-05T09:04:11.120118+00:00'
                        citation: ACT No. 3
                        approvedDate: '2025-06-20'
                        textAccess: none
                    count: 1
                    currentVersion: 1
                    truncated: false
                    creditsConsumed: 1
                    processingTimeMs: 19.7
          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: >-
            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:
              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: `sessionLawId` empty or over 300
            characters. 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:
                idTooLong:
                  summary: A `sessionLawId` of more than 300 characters
                  value:
                    detail: Invalid request parameters
                    errors:
                      - loc:
                          - path
                          - session_law_id
                        msg: String should have at most 300 characters
                        type: string_too_long
                emptyId:
                  summary: An empty `sessionLawId`
                  value:
                    detail: Invalid request parameters
                    errors:
                      - loc:
                          - path
                          - session_law_id
                        msg: String should have at least 1 character
                        type: string_too_short
              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:
    SessionLawVersionsResponse:
      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 these versions belong to.
          examples:
            - SSL_MN_2025S1_G_Y2025_C1
        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
        textReliability:
          anyOf:
            - type: string
              enum:
                - verified
                - unverified
                - known_issue
            - type: 'null'
          title: Textreliability
          description: >-
            How far to trust the CURRENT text of this law, the same field as on
            `/body`: `verified` when the text passed our strike-through check,
            `unverified` when that check has not been completed, `known_issue`
            when we have evidence the text shows deleted law as if enacted. A
            served law can be any of the three (its text is still served); a
            held-back law is `unverified` or `known_issue` and its text is read
            with `includeUnverified=true`. Omitted when no text of this law may
            be read.
          examples:
            - verified
        reasonCode:
          anyOf:
            - type: string
            - type: 'null'
          title: Reasoncode
          description: >-
            Why the text is not `verified`, the same token as on `/body`.
            Omitted when the text is `verified`.
          examples:
            - strike_unchecked
        versions:
          items:
            $ref: '#/components/schemas/SessionLawVersion'
          type: array
          title: Versions
          description: >-
            Every version we served or adopted, newest first, at most 100 of
            them (see `truncated`). At least the current one, except when `note`
            says the registry lists none.
        count:
          type: integer
          title: Count
          description: Number of versions listed.
          examples:
            - 2
        currentVersion:
          anyOf:
            - type: integer
            - type: 'null'
          title: Currentversion
          description: >-
            The `version` that is current. Null only when no version is current,
            which a served law never is.
          examples:
            - 2
        truncated:
          type: boolean
          title: Truncated
          description: >-
            True when the law has more versions than one answer lists, so
            `versions` is the newest ones and older versions exist that are not
            shown. False when `versions` is the whole history.
          default: false
          examples:
            - false
        note:
          anyOf:
            - type: string
            - type: 'null'
          title: Note
          description: >-
            Set only when the law exists but the registry lists no version of
            its text for it (`versions` is empty, `count` is 0): the answer is
            free, nothing is charged. Omitted otherwise.
          examples:
            - >-
              The registry holds this law but lists no version of its text for
              it (its current version is not set: the law may be withdrawn,
              merged into another law, or its text not yet recorded). There is
              nothing to read, so nothing was charged.
      type: object
      required:
        - sessionLawId
        - textStatus
        - count
      title: SessionLawVersionsResponse
      description: Response for `GET /us/session-laws/{sessionLawId}/versions`.
    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`.
    SessionLawVersion:
      properties:
        version:
          type: integer
          title: Version
          description: >-
            The version number, 1 for the first we recorded. Send it as
            `version` on `GET /us/session-laws/{sessionLawId}/body`. Numbers can
            have gaps: a version we recorded and never served or adopted is not
            listed.
          examples:
            - 2
        isCurrent:
          type: boolean
          title: Iscurrent
          description: >-
            True for the version `GET /us/session-laws/{sessionLawId}` and a
            plain `/body` call serve now. Exactly one listed version is current.
          examples:
            - true
        recordedAt:
          type: string
          title: Recordedat
          description: >-
            When we recorded this version, ISO 8601 in UTC. Not an approval or
            effective date of the act: it dates our copy of the text.
          examples:
            - '2026-10-13T09:04:11.120118+00:00'
        citation:
          anyOf:
            - type: string
            - type: 'null'
          title: Citation
          description: >-
            The act's citation as the publisher printed it in this version. Null
            when none was recorded.
          examples:
            - CHAPTER 1--S.F.No. 3
        title:
          anyOf:
            - type: string
            - type: 'null'
          title: Title
          description: The act's title in this version. Null when none was recorded.
          examples:
            - Agriculture finance and policy; omnibus bill
        approvedDate:
          anyOf:
            - type: string
              format: date
            - type: 'null'
          title: Approveddate
          description: >-
            Approval date recorded in this version, ISO 8601. Null when none was
            recorded.
          examples:
            - '2025-06-14'
        totalChars:
          anyOf:
            - type: integer
            - type: 'null'
          title: Totalchars
          description: >-
            Length of this version's text in characters. Null when this version
            has no text.
          examples:
            - 310454
        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. Two versions with the same
            hash have the same text: only the record around it changed.
          examples:
            - 02693d5b55d4709bdd36fdccee4a9737d2655a3988a90daeb6b7c486ce50260b
        textMethod:
          anyOf:
            - type: string
            - type: 'null'
          title: Textmethod
          description: >-
            How the text of this version was taken from the source: for example
            `pdf_text_layer`, `html`, `xml`. Null when this version has no text.
          examples:
            - pdf_text_layer
        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
        textAccess:
          type: string
          enum:
            - served
            - includeUnverified
            - none
          title: Textaccess
          description: >-
            How this version's text can be read with `GET
            /us/session-laws/{sessionLawId}/body?version=N`. `served`: the law
            is served and this version has text, so a plain call reads it.
            `includeUnverified`: the law is held back (`textStatus: withheld`)
            and this text is readable only with `includeUnverified=true`,
            labelled by `textReliability`. `none`: there is no text to read for
            this version, or the law's text may not be published.
          examples:
            - served
      type: object
      required:
        - version
        - isCurrent
        - recordedAt
        - textAccess
      title: SessionLawVersion
      description: One version of a session law.
    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.