6.2 Parameters: URL segments, query strings, and request bodies

A stored query declares its inputs in the params schema (6.1). At execution, the runtime collects parameter values from several sources, coerces and validates them, and only then runs the query.

The three sources (later wins)

Running a query at /<spec-path>[/<extra>/<segments>], parameters are gathered from, in increasing precedence:

  1. Positional URL segments — path segments beyond the matched spec path become positionals "0", "1", … So if orders/by-status is the stored spec, GET /q/orders/by-status/open binds "0" = "open".
  2. Query-string pairs — non-$-prefixed query params bind by name: ?status=open&min=20. (The $-prefixed ones like $take are control params, not query inputs.)
  3. Request body — a JSON object body binds named params; a JSON array body binds positionals.

Later sources override earlier ones, so a body value beats a query-string value beats a URL segment.

Type coercion

Query-string and URL values arrive as strings, so they're coerced to the types the params schema declares: a param typed number/integer parses numerically, boolean parses true/false, anything else stays a string. This is what makes a plain link work:

GET /q/open-orders?status=open&min=20

min is declared number, so "20" becomes 20 before validation — you don't have to JSON-encode query params.

Defaults, then validation

The flow at execution:

  1. Collect values from the three sources.
  2. Apply schema defaults for any missing params.
  3. Validate the whole set against params.

A validation failure is 422 with an errors array (the same shape as data validation, 4.5). A missing required param is always a 400 — never a silent empty value. This is deliberate: a query never quietly runs with a blank where a required input should be.

Why this matters

Because params are typed, defaulted, and validated before the query runs, your stored queries are safe to expose directly to clients — including via a plain GET link or an agent that read the param schema off the agent surface (9.1). The next section shows how those validated values are substituted into the query without any injection risk.


Previous: 6.1 The query service · Manual home · Next: 6.3 JSON templates →