Skip to content

Querying & filtering

Every dataset endpoint (GET /v1/{domain}/{dataset}) supports the same query language: filters, sorting, and field selection, combined freely with pagination. The columns you can use are dataset-specific — find them on the dataset's reference page, in /v1/datasets/{id}, or in /docs.

Validation is strict. An unknown column, operator, or field anywhere in the query is a 422 with a message naming the offender — never a silently ignored parameter.

Filtering

Plain equality is just ?column=value:

curl -H "Authorization: Bearer $API_KEY" \
  "https://api.canovix.ro/v1/transport/vehicle_registry?county=CLUJ"
  • Text equality is case-insensitive (county=cluj matches CLUJ).
  • Repeat a parameter for OR: ?county=CLUJ&county=SIBIU matches either.

Everything else uses bracket operators — ?column[op]=value:

Operator Meaning Example
eq equal (same as no operator) county[eq]=CLUJ
ne not equal county[ne]=CLUJ
gt / gte greater than / or equal vehicle_count[gte]=100
lt / lte less than / or equal vehicle_count[lt]=50
in any of a comma-separated list county[in]=CLUJ,SIBIU,BIHOR
not_in none of a comma-separated list county[not_in]=CLUJ,SIBIU
contains substring match (case-insensitive) manufacturer[contains]=volks
starts_with prefix match (case-insensitive) manufacturer[starts_with]=DA
is_null null / not-null test (true/false) description[is_null]=true

Values are coerced to the column's type — integers, decimals, booleans, ISO dates (2023-12-31), and datetimes all work in comparisons. A value that can't be coerced is a 422.

Multiple filters on different columns combine with AND:

# Cluj county, at least 100 vehicles, manufacturer starting with "D"
curl -H "Authorization: Bearer $API_KEY" \
  "https://api.canovix.ro/v1/transport/vehicle_registry?county=CLUJ&vehicle_count[gte]=100&manufacturer[starts_with]=D"
params = {
    "county": "CLUJ",
    "vehicle_count[gte]": 100,
    "manufacturer[starts_with]": "D",
}
page = client.get("/v1/transport/vehicle_registry", params=params).json()
const params = new URLSearchParams({
  county: "CLUJ",
  "vehicle_count[gte]": "100",
  "manufacturer[starts_with]": "D",
});
const page = await (
  await fetch(`${BASE}/v1/transport/vehicle_registry?${params}`, {
    headers: { Authorization: `Bearer ${API_KEY}` },
  })
).json();

Sorting

?sort= takes a comma-separated list of columns; prefix with - for descending. Later fields break ties on earlier ones.

# Largest fleets first, alphabetical manufacturer within equal counts
curl -H "Authorization: Bearer $API_KEY" \
  "https://api.canovix.ro/v1/transport/vehicle_registry?sort=-vehicle_count,manufacturer"

Without ?sort=, rows come back in a stable default order (the dataset's primary key). Sorting cannot be combined with cursor pagination.

Field selection

?fields= projects the response down to the columns you name — smaller payloads, less parsing:

curl -H "Authorization: Bearer $API_KEY" \
  "https://api.canovix.ro/v1/transport/vehicle_registry?fields=county,manufacturer,vehicle_count&limit=2"
{
  "data": [
    { "county": "ALBA", "manufacturer": "AUDI", "vehicle_count": 4581 },
    { "county": "ALBA", "manufacturer": "BMW", "vehicle_count": 3717 }
  ],
  "pagination": { "total": 382667, "count": 2, "limit": 2, "offset": 0, "has_next": true, "next_offset": 2 },
  "meta": { "api_version": "v1", "dataset": "vehicle_registry", "domain": "transport", "last_updated": "...", "generated_at": "..." },
  "links": { "self": "...", "next": "..." }
}

The projection happens in SQL, not after the fact — asking for 3 columns of a wide table genuinely reads less data.

Raw vs canonical columns

Some datasets carry both a raw column (exactly what the source file said) and a canonical sibling standardized against a shared reference table — e.g. vehicle_registry has manufacturer (raw) and manufacturer_canonical (standardized spelling). Filter and aggregate on the canonical column when you want variants like VW, VOLKSWAGEN, and Volkswagen AG treated as one thing; use the raw column when you need source fidelity.