Querying tables
Read table rows as JSON with column selection, filtering, sorting and offset pagination — documented against the live API.
Last updated on
Read rows from a table as JSON with the query endpoint. The query is sent as a JSON request body:
POST/namespaces/{namespace}/tables/{tableName}/query
It returns the rows plus offset pagination metadata:
{ "data": [ /* rows */ ], "total": 22143, "total_pages": 4429, "current_page": 1 }Request body
Send a JSON object. Every field is optional — an empty body {} returns the
first page of all columns.
| Parameter | Type | Description |
|---|---|---|
select | string | Comma-separated column names to return. Omit for all columns. |
filter | string | Filter expression: column=value conditions with optional operators and _and/_or (see below). |
sort | string | Comma-separated sort keys. Prefix - for descending, + or none for ascending. |
limit | int | Maximum rows to return (page size). |
offset= 0 | int | Rows to skip — offset = (page − 1) × limit. |
exclude_nulls | string[] | Column name(s) that must be non-null; rows with a null there are dropped. |
Select columns
select is a comma-separated projection. Omit it to get every column.
curl -X POST 'https://api.dataportal.gov.lt/namespaces/111958286/tables/mirusiuju_toksikologinis_rezultatas/query' \
-H 'Content-Type: application/json' \
-d '{"select":"lytis,mirties_metai,pavadinimas","limit":3}'Filter
filter is a URL-style expression carried in the body as a string: column=value
conditions joined with &, optionally using comparison operators and _and /
_or groups. Values are written bare — no quotes needed, even for text with
spaces.
# Equality — female decedents (5 243 rows)
curl -X POST 'https://api.dataportal.gov.lt/namespaces/111958286/tables/mirusiuju_toksikologinis_rezultatas/query' \
-H 'Content-Type: application/json' \
-d '{"filter":"lytis=Moteris","limit":1}'Operators
Append a dotted, two-letter operator to the column. Omit it for equality.
| Parameter | Type | Description |
|---|---|---|
col=v | equals | Exact match (e.g. lytis=Moteris). |
col._gt=v | greater than | e.g. mirties_metai._gt=2020 |
col._ge=v | ≥ | greater than or equal |
col._lt=v | less than | |
col._le=v | ≤ | less than or equal |
col._co=v | contains | substring match (e.g. pavadinimas._co=Etan) |
col._sw=v | starts with | |
col._ew=v | ends with |
# Substance name containing "Etan" (13 345 rows)
curl -X POST 'https://api.dataportal.gov.lt/namespaces/111958286/tables/mirusiuju_toksikologinis_rezultatas/query' \
-H 'Content-Type: application/json' \
-d '{"filter":"pavadinimas._co=Etan","limit":1}'Use the two-letter operators
The operator names are two letters: ._ge / ._le, not ._gte / ._lte.
The three-letter forms are rejected by the query engine (they come back as a
502). (Some spec examples show ._gte — that is a spec bug.)
Combining conditions — _and / _or
Join conditions inside the filter string with &. Each extra condition is
_and by default; prefix it with _or. for a disjunction. The operator (or none,
for equality) still dots onto the column.
# 2018+ AND female (4 570 rows)
curl -X POST 'https://api.dataportal.gov.lt/namespaces/111958286/tables/mirusiuju_toksikologinis_rezultatas/query' \
-H 'Content-Type: application/json' \
-d '{"filter":"mirties_metai._ge=2018&_and.lytis=Moteris","limit":1}'
# female OR male
curl -X POST 'https://api.dataportal.gov.lt/namespaces/111958286/tables/mirusiuju_toksikologinis_rezultatas/query' \
-H 'Content-Type: application/json' \
-d '{"filter":"lytis=Moteris&_or.lytis=Vyras","limit":1}'The response total reflects the filtered set, so it's the quickest way to check
a filter is doing what you expect.
Sort
sort takes comma-separated column names. Prefix - for descending, + (or
nothing) for ascending.
# Newest deaths first
curl -X POST 'https://api.dataportal.gov.lt/namespaces/111958286/tables/mirusiuju_toksikologinis_rezultatas/query' \
-H 'Content-Type: application/json' \
-d '{"sort":"-mirties_metai","limit":5}'Pagination
Pagination is offset-based and maps straight to SQL LIMIT / OFFSET:
-
limit— page size -
offset— rows to skip;offset = (page − 1) × limit
The response reports total (all matching rows), total_pages (for the current
limit), and current_page.
First page
curl -X POST '…/query' -H 'Content-Type: application/json' -d '{"limit":100,"offset":0}'Next page
Add limit to the offset each time — page 2 is offset=100, page 3 offset=200, …
curl -X POST '…/query' -H 'Content-Type: application/json' -d '{"limit":100,"offset":100}'Stop
When current_page reaches total_pages (or fewer than limit rows come back), you're done.
Walk every page
A copy-paste loop that pages through the whole table until the last (short) page:
URL='https://api.dataportal.gov.lt/namespaces/111958286/tables/mirusiuju_toksikologinis_rezultatas/query'
LIMIT=1000
OFFSET=0
while :; do
RESP=$(curl -s -X POST "$URL" -H 'Content-Type: application/json' \
-d "{\"limit\":$LIMIT,\"offset\":$OFFSET,\"sort\":\"_id\"}")
COUNT=$(echo "$RESP" | jq '.data | length')
echo "offset=$OFFSET got=$COUNT total=$(echo "$RESP" | jq '.total')"
[ "$COUNT" -lt "$LIMIT" ] && break # last page: fewer than limit rows
OFFSET=$((OFFSET + LIMIT))
doneimport requests
URL = "https://api.dataportal.gov.lt/namespaces/111958286/tables/mirusiuju_toksikologinis_rezultatas/query"
limit, offset = 1000, 0
while True:
resp = requests.post(URL, json={"limit": limit, "offset": offset, "sort": "_id"}).json()
rows = resp["data"]
print(f"offset={offset} got={len(rows)} total={resp['total']}")
if len(rows) < limit:
break # last page
offset += limitconst URL = "https://api.dataportal.gov.lt/namespaces/111958286/tables/mirusiuju_toksikologinis_rezultatas/query";
const limit = 1000;
let offset = 0;
while (true) {
const resp = await (await fetch(URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ limit, offset, sort: "_id" }),
})).json();
console.log(`offset=${offset} got=${resp.data.length} total=${resp.total}`);
if (resp.data.length < limit) break; // last page
offset += limit;
}Two things that bite
- Always add a stable
sort(e.g.sort=_id). Without a fixed order the query engine may return rows differently between requests, so offset paging can skip or repeat rows. Afiltershrinkstotal, so you page the filtered set. - Deep offsets get slow —
OFFSETstill scans the rows it skips. To pull the whole table, don't paginate at all: use the export endpoint, which streams the entire result set in one request.
Drop null rows
exclude_nulls names one or more columns that must be non-null; rows with a null
in any of them are dropped from the result. Pass it as a JSON array:
curl -X POST '…/query' -H 'Content-Type: application/json' \
-d '{"exclude_nulls":["m_konc","pavadinimas"],"limit":5}'Try it
Build a query against the live table and run it:
curl -X POST 'https://api.dataportal.gov.lt/namespaces/111958286/tables/mirusiuju_toksikologinis_rezultatas/query' \
-H 'Content-Type: application/json' \
-d '{"limit":10,"select":"pavadinimas,lytis,mirties_metai,gyv_tipas","sort":"mirties_metai","filter":"lytis=Moteris"}'| lytis | mirties_metai | pavadinimas | gyv_tipas |
|---|---|---|---|
| Moteris | 2021 | Etanolis (etilo alkoholis) | Kaimas |
Downloading data
When you want the whole result set as a file.
Errors
What 400 / 404 / 502 responses look like.
See also
How is this guide?