curl --request GET \
--url https://api.vaquill.ai/api/v1/us/session-laws/changes \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.vaquill.ai/api/v1/us/session-laws/changes"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.vaquill.ai/api/v1/us/session-laws/changes', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.vaquill.ai/api/v1/us/session-laws/changes"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}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
curl "https://api.vaquill.ai/api/v1/us/session-laws/changes?sinceId=0&limit=100" \
-H "Authorization: Bearer $VAQUILL_API_KEY"
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/listlists the laws of one state, filtered; this feed is how you learn that one changed.POST /us/session-laws/batchreads many laws at once from the ids this feed returns.GET /us/statutes/coveragesays which sessions we hold and how complete each is, in each jurisdiction’ssessionLawsblock.
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.
curl --request GET \
--url https://api.vaquill.ai/api/v1/us/session-laws/changes \
--header 'Authorization: Bearer <token>'import requests
url = "https://api.vaquill.ai/api/v1/us/session-laws/changes"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://api.vaquill.ai/api/v1/us/session-laws/changes', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.vaquill.ai/api/v1/us/session-laws/changes"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "Bearer <token>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Authorizations
API key issued from the developer dashboard. Pass as Authorization: Bearer vq_key_... (preferred).
Query Parameters
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.
0 <= x <= 92233720368547760001500
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.
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 "mn"
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.
1 <= x <= 200100
Response
A page of the feed, oldest first. hasMore and cursor say how to continue; an empty changes is a charged answer.
Response for GET /us/session-laws/changes.
The entries after sinceId, oldest first, at most limit. Empty when nothing changed since your cursor, which is an answer and is charged.
Show child attributes
Show child attributes
Entries on this page.
2
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.
1502
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.
true
Credits actually charged for this call, never the list price. 0 when the call was refunded (a failure on our side).
1
Server-side time for this request in milliseconds, excluding network transit. Not billed on.
41.8
Was this page helpful?

