6.5 Param schemas, defaults, and validation
The params block of a query envelope is a plain JSON Schema describing the
query's inputs. It does three jobs: it types the inputs (so coercion works), it
supplies defaults, and it validates — and it's also what the agent surface
advertises so callers know how to invoke the query.
What params declares
"params": {
"type": "object",
"required": ["status"],
"properties": {
"status": { "type": "string" },
"min": { "type": "number", "default": 0 },
"limit": { "type": "integer", "default": 50 }
}
}
type/properties— the parameter names and their types. Types drive the coercion of string-sourced values (URL segments, query strings) into numbers, integers, and booleans (6.2).required— a missing required param is a hard400at execution.default— applied for any param the caller omitted, before validation.
The execution order (recap)
- Collect raw values from URL segments, query string, and body (6.2).
- Coerce string-sourced values to declared types.
- Apply
defaults for missing params. - Validate the full set against
params. - Substitute (structurally for JSON, by binding for SQL) and run.
A failure at step 4 is 422 validation_failed with an errors array of
{path, error}; a missing required param surfaces as 400. Either way the query
does not run with bad inputs.
Validated at write and read
The param schema itself is compiled and checked when you PUT the query spec —
a non-compiling schema is rejected at authoring time, not deferred to the first
execution. So a stored query is always either valid-and-runnable or rejected; it
can't sit in a half-broken state.
The agent surface reads it live
Stored queries appear on the agent surface (/.well-known/rs2/agent-surface,
9.1) with their params and output schemas, read live from the store. That
means an API consumer — or an AI agent — can discover exactly how to call a query
(which params, which types, which are required) without documentation drift: the
schema enforced at runtime is the schema advertised.
Design tips
- Give optional filters a sensible
default, or pair them with the optional placeholder"${name?}"(6.3) so they vanish when unset. - Type numeric and boolean params precisely so plain links and forms work without JSON-encoding values.
- Keep
requiredminimal — every required param is a way for a caller to get a400.
The final section of this part uses the same store-view idea to render HTML from request data. After that, Part 7 moves from reading data to composing services into multi-step flows.
← Previous: 6.4 String/SQL templates · Manual home · Next: 6.6 Rendering HTML with templates →