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

# Feed of changes to the session-law registry

> A sync feed of the registry: every state law that began to be served, had its text added, was
corrected, unserved, withdrawn or merged, oldest first, as a cursor over an integer `id`. Poll it
to keep a copy of the registry current without re-listing it: read from `sinceId=0` once, then
call again with the `cursor` you were given.

**Cost**: 1 credit per page of up to 200 entries (default 50). An empty
page is an answer, "nothing changed since your cursor", and is charged. A request that fails
validation (422) is never charged; a failure on our side (500, 503) is refunded.

**Walking the feed.** Send `sinceId=0` for the first page. While `hasMore` is true, call again with
`sinceId` set to `cursor`: the feed is ordered by `id`, `id` only grows, and a page carries the
entries after `sinceId` and nothing else, so no entry is skipped or repeated between your calls.
When `hasMore` is false you have caught up as of this call; keep your cursor and ask again later.
An empty page has `cursor: null`: keep the one you hold.

**What an entry says.** `kind` is what happened (see its description), `sessionLawId` the law,
`jurisdiction` its state, and `detectedAt` when we recorded it, an upper bound on when the law
changed in the world and never an approval or effective date. Read the law itself at
`GET /us/session-laws/{sessionLawId}`, or many at once with `POST /us/session-laws/batch`. A
`withdrawn` or `merged` entry is a tombstone: the law no longer answers there.

**Filter.** `jurisdiction` limits the feed to one state, `dc` or `pr`, and then `hasMore` means
more MATCHING entries follow. The cursor is a position in the whole feed, so the same `sinceId`
means the same point with or without the filter, and a filtered page can skip ids.

**Read a short window behind your cursor.** `id` is assigned in order but a row can become visible
slightly after a later one if two writers commit at once. Every writer today commits a whole
batch together, so this has not happened, but a job that must never miss an entry should re-read
the last few hundred ids it has already seen.

**Scope.** State session laws only: federal acts (`SAL_...`) are never in this feed.

**Example**

```bash
curl "https://api.vaquill.ai/api/v1/us/session-laws/changes?sinceId=0&limit=100" \
  -H "Authorization: Bearer $VAQUILL_API_KEY"
```

```javascript
let cursor = 0;
for (;;) {
  const res = await fetch(`https://api.vaquill.ai/api/v1/us/session-laws/changes?sinceId=${cursor}`, {
    headers: { Authorization: `Bearer ${process.env.VAQUILL_API_KEY}` },
  });
  const page = await res.json();
  for (const change of page.changes) handle(change);
  if (page.cursor !== null) cursor = page.cursor;
  if (!page.hasMore) break;
}
```

**Related endpoints**

- `GET /us/session-laws/list` lists the laws of one state, filtered; this feed is how you learn
  that one changed.
- `POST /us/session-laws/batch` reads many laws at once from the ids this feed returns.
- `GET /us/statutes/coverage` says which sessions we hold and how complete each is, in each
  jurisdiction's `sessionLaws` block.

**Nulls.** Every field of a response is always present: one with no value is `null` (or `[]`
for a list). The examples on this page leave the nulls out for brevity.



## OpenAPI

````yaml https://api.vaquill.ai/external/openapi.json get /api/v1/us/session-laws/changes
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. The `api_key` query parameter also
    works where a header cannot be set, but a URL ends up in logs and browser
    history. 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 52 state and territory statutory codes (50 states plus DC and
    Puerto Rico), 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
  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
servers:
  - url: https://api.vaquill.ai
    description: Production
security:
  - ApiKeyAuth: []
  - ApiKeyHeader: []
  - ApiKeyQuery: []
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: 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: 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/changes:
    get:
      tags:
        - US Session Laws
      summary: Feed of changes to the session-law registry
      description: >-
        A sync feed of the registry: every state law that began to be served,
        had its text added, was

        corrected, unserved, withdrawn or merged, oldest first, as a cursor over
        an integer `id`. Poll it

        to keep a copy of the registry current without re-listing it: read from
        `sinceId=0` once, then

        call again with the `cursor` you were given.


        **Cost**: 1 credit per page of up to 200 entries (default 50). An empty

        page is an answer, "nothing changed since your cursor", and is charged.
        A request that fails

        validation (422) is never charged; a failure on our side (500, 503) is
        refunded.


        **Walking the feed.** Send `sinceId=0` for the first page. While
        `hasMore` is true, call again with

        `sinceId` set to `cursor`: the feed is ordered by `id`, `id` only grows,
        and a page carries the

        entries after `sinceId` and nothing else, so no entry is skipped or
        repeated between your calls.

        When `hasMore` is false you have caught up as of this call; keep your
        cursor and ask again later.

        An empty page has `cursor: null`: keep the one you hold.


        **What an entry says.** `kind` is what happened (see its description),
        `sessionLawId` the law,

        `jurisdiction` its state, and `detectedAt` when we recorded it, an upper
        bound on when the law

        changed in the world and never an approval or effective date. Read the
        law itself at

        `GET /us/session-laws/{sessionLawId}`, or many at once with `POST
        /us/session-laws/batch`. A

        `withdrawn` or `merged` entry is a tombstone: the law no longer answers
        there.


        **Filter.** `jurisdiction` limits the feed to one state, `dc` or `pr`,
        and then `hasMore` means

        more MATCHING entries follow. The cursor is a position in the whole
        feed, so the same `sinceId`

        means the same point with or without the filter, and a filtered page can
        skip ids.


        **Read a short window behind your cursor.** `id` is assigned in order
        but a row can become visible

        slightly after a later one if two writers commit at once. Every writer
        today commits a whole

        batch together, so this has not happened, but a job that must never miss
        an entry should re-read

        the last few hundred ids it has already seen.


        **Scope.** State session laws only: federal acts (`SAL_...`) are never
        in this feed.


        **Example**


        ```bash

        curl
        "https://api.vaquill.ai/api/v1/us/session-laws/changes?sinceId=0&limit=100"
        \
          -H "Authorization: Bearer $VAQUILL_API_KEY"
        ```


        ```javascript

        let cursor = 0;

        for (;;) {
          const res = await fetch(`https://api.vaquill.ai/api/v1/us/session-laws/changes?sinceId=${cursor}`, {
            headers: { Authorization: `Bearer ${process.env.VAQUILL_API_KEY}` },
          });
          const page = await res.json();
          for (const change of page.changes) handle(change);
          if (page.cursor !== null) cursor = page.cursor;
          if (!page.hasMore) break;
        }

        ```


        **Related endpoints**


        - `GET /us/session-laws/list` lists the laws of one state, filtered;
        this feed is how you learn
          that one changed.
        - `POST /us/session-laws/batch` reads many laws at once from the ids
        this feed returns.

        - `GET /us/statutes/coverage` says which sessions we hold and how
        complete each is, in each
          jurisdiction's `sessionLaws` block.

        **Nulls.** Every field of a response is always present: one with no
        value is `null` (or `[]`

        for a list). The examples on this page leave the nulls out for brevity.
      operationId: get_session_law_changes_api_v1_us_session_laws_changes_get
      parameters:
        - name: sinceId
          in: query
          required: false
          schema:
            type: integer
            maximum: 9223372036854776000
            minimum: 0
            description: >-
              Return only entries with an `id` greater than this: the cursor for
              walking the feed forward. Send 0 (the default) to start from the
              beginning, then the `cursor` of your last page. `id` is an integer
              that only grows, so this is exact and immune to clock skew. A
              negative or non-integer value is a 422 and is never charged; a
              value past the newest `id` is an empty page, which is charged.
            examples:
              - 1500
            default: 0
            title: Sinceid
          description: >-
            Return only entries with an `id` greater than this: the cursor for
            walking the feed forward. Send 0 (the default) to start from the
            beginning, then the `cursor` of your last page. `id` is an integer
            that only grows, so this is exact and immune to clock skew. A
            negative or non-integer value is a 422 and is never charged; a value
            past the newest `id` is an empty page, which is charged.
        - name: jurisdiction
          in: query
          required: false
          schema:
            anyOf:
              - type: string
                enum:
                  - al
                  - ak
                  - as
                  - az
                  - ar
                  - ca
                  - co
                  - ct
                  - de
                  - dc
                  - fl
                  - ga
                  - gu
                  - hi
                  - id
                  - il
                  - in
                  - ia
                  - ks
                  - ky
                  - la
                  - me
                  - md
                  - ma
                  - mi
                  - mn
                  - ms
                  - mo
                  - mt
                  - ne
                  - nv
                  - nh
                  - nj
                  - nm
                  - ny
                  - nc
                  - nd
                  - mp
                  - oh
                  - ok
                  - or
                  - pa
                  - pr
                  - ri
                  - sc
                  - sd
                  - tn
                  - tx
                  - ut
                  - vt
                  - vi
                  - va
                  - wa
                  - wv
                  - wi
                  - wy
              - type: 'null'
            description: >-
              Limit the feed to one jurisdiction: a two-letter state code, `dc`
              or `pr`, case-insensitive. Omit for every jurisdiction. `federal`
              and any unknown code is a 422 and is never charged: federal
              session laws are not in this feed. The cursor is a position in the
              whole feed, so a filtered page may have gaps in `id`.
            examples:
              - mn
            title: Jurisdiction
          description: >-
            Limit the feed to one jurisdiction: a two-letter state code, `dc` or
            `pr`, case-insensitive. Omit for every jurisdiction. `federal` and
            any unknown code is a 422 and is never charged: federal session laws
            are not in this feed. The cursor is a position in the whole feed, so
            a filtered page may have gaps in `id`.
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            maximum: 200
            minimum: 1
            description: >-
              Most entries on this page: 1 to 200, default 50. The price is per
              page, however many entries it holds, so a larger page is cheaper
              per entry. Out of range is a 422 and is never charged.
            examples:
              - 100
            default: 50
            title: Limit
          description: >-
            Most entries on this page: 1 to 200, default 50. The price is per
            page, however many entries it holds, so a larger page is cheaper per
            entry. Out of range is a 422 and is never charged.
      responses:
        '200':
          description: >-
            A page of the feed, oldest first. `hasMore` and `cursor` say how to
            continue; an empty `changes` is a charged answer.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SessionLawChangesResponse'
              examples:
                page:
                  summary: 'A full page: more follow, so call again with `sinceId=1502`'
                  value:
                    changes:
                      - id: 1501
                        kind: served
                        sessionLawId: SSL_MN_2025R_G_Y2025_C1
                        jurisdiction: mn
                        detectedAt: '2026-10-05T09:04:11.120118+00:00'
                      - id: 1502
                        kind: served
                        sessionLawId: SSL_MN_2025R_G_Y2025_C10
                        jurisdiction: mn
                        detectedAt: '2026-10-05T09:04:11.120118+00:00'
                    count: 2
                    cursor: 1502
                    hasMore: true
                    creditsConsumed: 1
                    processingTimeMs: 41.8
                caughtUp:
                  summary: >-
                    Nothing since your cursor: charged, `cursor` null, keep the
                    one you hold
                  value:
                    changes: []
                    count: 0
                    hasMore: false
                    creditsConsumed: 1
                    processingTimeMs: 12.4
        '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'
        '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:
              schema:
                $ref: '#/components/schemas/ApiDetailError'
              example:
                detail: Insufficient credits
        '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'
        '422':
          description: >-
            A parameter failed validation: `sinceId` negative or not an integer,
            `limit` out of range, or `jurisdiction` not a state. Never charged.
            `errors[].loc` names the parameter exactly as you send it.
          content:
            application/json:
              examples:
                negativeSinceId:
                  summary: '`sinceId=-1`'
                  value:
                    detail: Invalid request parameters
                    errors:
                      - loc:
                          - query
                          - sinceId
                        msg: Input should be greater than or equal to 0
                        type: greater_than_equal
                limitTooLarge:
                  summary: '`limit=500`: at most 200'
                  value:
                    detail: Invalid request parameters
                    errors:
                      - loc:
                          - query
                          - limit
                        msg: Input should be less than or equal to 200
                        type: less_than_equal
                federalJurisdiction:
                  summary: '`jurisdiction=federal`: federal acts are never in this feed'
                  value:
                    detail: Invalid request parameters
                    errors:
                      - loc:
                          - query
                          - jurisdiction
                        msg: >-
                          Value error, Unknown `jurisdiction` value 'federal'.
                          Expected one of: ak, al, ar, as, az, ca, co, ct, dc,
                          de, fl, ga, gu, hi, ia, id, il, in, ks, ky, la, ma,
                          md, me, mi, mn, mo, mp, ms, mt, nc, nd, ne, nh, nj,
                          nm, nv, ny, oh, ok, or, pa, pr, ri, sc, sd, tn, tx,
                          ut, va, vi, vt, wa, wi, wv, wy.
                        type: value_error
              schema:
                $ref: '#/components/schemas/ApiDetailError'
        '429':
          description: >-
            Rate limit exceeded for your key. Not charged. Wait `Retry-After`
            seconds.
          headers:
            Retry-After:
              description: Seconds to wait before retrying.
              schema:
                type: integer
                examples:
                  - 12
            X-RateLimit-Limit:
              description: Requests per minute your key is allowed.
              schema:
                type: integer
                examples:
                  - 60
            X-RateLimit-Remaining:
              description: Requests left in the current minute. 0 on a 429.
              schema:
                type: integer
                examples:
                  - 0
            X-RateLimit-Reset:
              description: Unix time at which the minute window resets.
              schema:
                type: integer
                examples:
                  - 1791194460
          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'
        '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'
components:
  schemas:
    SessionLawChangesResponse:
      properties:
        changes:
          items:
            $ref: '#/components/schemas/SessionLawChange'
          type: array
          title: Changes
          description: >-
            The entries after `sinceId`, oldest first, at most `limit`. Empty
            when nothing changed since your cursor, which is an answer and is
            charged.
        count:
          type: integer
          title: Count
          description: Entries on this page.
          default: 0
          examples:
            - 2
        cursor:
          anyOf:
            - type: integer
            - type: 'null'
          title: Cursor
          description: >-
            The largest `id` on this page: send it as `sinceId` for the next
            page. Null when the page is empty, so keep the cursor you already
            hold.
          examples:
            - 1502
        hasMore:
          type: boolean
          title: Hasmore
          description: >-
            True when more entries follow this page: call again with `sinceId`
            set to `cursor` straight away. False means you have caught up as of
            this call.
          default: false
          examples:
            - true
        creditsConsumed:
          type: integer
          title: Creditsconsumed
          description: >-
            Credits actually charged for this call, never the list price. 0 when
            the call was refunded (a failure on our side).
          default: 0
          examples:
            - 1
        processingTimeMs:
          type: number
          title: Processingtimems
          description: >-
            Server-side time for this request in milliseconds, excluding network
            transit. Not billed on.
          default: 0
          examples:
            - 41.8
      type: object
      title: SessionLawChangesResponse
      description: Response for `GET /us/session-laws/changes`.
    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.'
      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.
    SessionLawChange:
      properties:
        id:
          type: integer
          title: Id
          description: >-
            The entry's position in the feed: an integer that only ever grows.
            Send the largest `id` you hold as `sinceId` to read what came after
            it.
          examples:
            - 1501
        kind:
          type: string
          enum:
            - added
            - text_available
            - corrected
            - served
            - unserved
            - withdrawn
            - merged
          title: Kind
          description: >-
            What happened to the law. `added`: the registry learned the act
            exists. `text_available`: its text was collected. `corrected`: our
            reading of the law (its identity, dates or text) was corrected, so a
            copy you hold may be stale. `served`: it began to be served by this
            API. `unserved`: it stopped being served. `withdrawn`: it was
            removed from the registry, a tombstone: `GET
            /us/session-laws/{sessionLawId}` no longer answers it. `merged`: it
            was found to be the same law as another and merged into it, also a
            tombstone. So far every entry is `served`, one per law served when
            the registry went live; the other kinds appear as laws change. A
            consumer should treat a kind it does not know as `corrected`:
            re-read the law.
          examples:
            - served
        sessionLawId:
          type: string
          title: Sessionlawid
          description: >-
            The law this entry is about. Read it at `GET
            /us/session-laws/{sessionLawId}`, except after `withdrawn` or
            `merged`, when it no longer answers.
          examples:
            - SSL_MN_2025R_G_Y2025_C1
        jurisdiction:
          type: string
          title: Jurisdiction
          description: Lowercase two-letter code of the state, `dc` or `pr`.
          examples:
            - mn
        detectedAt:
          type: string
          title: Detectedat
          description: >-
            When we recorded the change, ISO 8601 in UTC: the start of the
            transaction that wrote it. An upper bound on when the law changed in
            the world, never the date the law took effect or was approved.
          examples:
            - '2026-10-05T09:04:11.120118+00:00'
      type: object
      required:
        - id
        - kind
        - sessionLawId
        - jurisdiction
        - detectedAt
      title: SessionLawChange
      description: One entry of the registry feed.
    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
              - corpusType
        msg:
          type: string
          title: Msg
          description: What is wrong with the value, in plain English.
          examples:
            - Input should be 'USC', 'CFR' or 'STATE'
        type:
          type: string
          title: Type
          description: >-
            Machine-readable error kind, e.g. `missing`, `literal_error`,
            `json_invalid`.
          examples:
            - literal_error
      type: object
      required:
        - loc
        - msg
        - type
      title: ApiFieldError
      description: One rejected field in a 422 response.
  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.
    ApiKeyQuery:
      type: apiKey
      in: query
      name: api_key
      description: >-
        The same API key as a query parameter: `?api_key=vq_key_...`. Use only
        where you cannot set a header. A URL can end up in proxy and server
        logs, browser history and shared links, so prefer either header form,
        and rotate a key that has leaked.

````

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