<!--
SPDX-FileCopyrightText: 2026 Arcangelo Massari <arcangelo.massari@unibo.it>

SPDX-License-Identifier: CC-BY-4.0
-->

# Query parameters

Query parameters are passed as standard HTTP query string arguments. They are applied after the SPARQL query returns and after postprocessing, in this fixed order: require, filter, sort, format/json. Pagination (`page`, `page_size`) is applied last, after all filtering and sorting.

Operations can override any of these built-in parameters with a [custom parameter handler](custom-parameters) via the `#custom_params` field. When overridden, the built-in behavior is replaced by the custom handler.

## require

Remove rows where a field is empty.

```
?require=author
?require=author&require=venue
```

## filter

Keep only rows matching a condition. Three modes:

**Regex** (no operator): the value is treated as a regular expression.

```
?filter=title:opencitations
```

**Comparison** (`=`, `<`, `>`): compared using the field's declared type from `#field_type`.

```
?filter=pub_date:>2020
?filter=volume:=5
?filter=pub_date:<2024
```

Multiple filters stack:

```
?filter=pub_date:>2020&filter=type:journal article
```

## sort

Sort rows by a field in ascending or descending order.

```
?sort=asc(pub_date)
?sort=desc(pub_date)
```

Multiple sort parameters are applied in sequence:

```
?sort=asc(pub_date)&sort=desc(title)
```

## format

Override the response format. Takes priority over the `Accept` header.

```
?format=csv
?format=json
```

Custom formats registered via [`#format`](format-converters) are also available (e.g., `?format=xml`).

(content-negotiation)=
## Content negotiation

When no `?format=` parameter is present, RAMOSE selects the response format from the request's `Accept` header, matching it against what the operation can produce: built-in `application/json` and `text/csv`, plus any custom format that declares a media type (the third field of [`#format`](format-converters)).

Precedence is `?format=` > `Accept` > operation default:

- `?format=` always wins, so existing clients keep their behavior.
- Otherwise the best matching media type from `Accept` is used.
- If `Accept` is absent, `*/*`, or matches nothing the operation produces, the operation default applies (`#default_format`, or JSON when unset).

```sh
curl -H "Accept: text/csv" "http://localhost:8080/v1/metadata/doi:10.1162/qss_a_00292"
curl -H "Accept: application/json" "http://localhost:8080/v1/metadata/doi:10.1162/qss_a_00292"
```

A custom format is Accept-negotiable only when it declares a media type; without one it stays reachable through `?format=`.

## json

Transform fields in JSON responses. Only applies when the output format is JSON.

**array**: split a string into an array by separator.

```
?json=array("; ", author)
```

`"Massari, Arcangelo [orcid:0000-0002-8420-0696 omid:ra/06250110138]; Mariani, Fabio [orcid:0000-0002-7382-0187 omid:ra/0621012370562]"` becomes `["Massari, Arcangelo [orcid:0000-0002-8420-0696 omid:ra/06250110138]", "Mariani, Fabio [orcid:0000-0002-7382-0187 omid:ra/0621012370562]"]`.

**dict**: split a string into an object with named keys.

```
?json=dict(", ", author, family, given)
```

`"Massari, Arcangelo"` becomes `{"family": "Massari", "given": "Arcangelo"}`.

Both transformations work on nested paths using dot notation:

```
?json=array(";", person.names)
```

Multiple transformations can be chained. Each one operates on the result of the previous:

```
?json=array("; ", author)&json=dict(", ", author, family, given)
```

## page and page_size

Paginate results by specifying the page size and the page number. Without these parameters, all results are returned.

```
?page_size=10
?page=2&page_size=10
```

`page_size` sets the number of items per page. `page` selects which page to return (1-indexed, defaults to 1 when only `page_size` is provided).

When pagination is active, the response includes a `Link` HTTP header with navigation URLs using relation types from the [IANA Link Relations registry](https://www.iana.org/assignments/link-relations/), serialized following [RFC 8288](https://www.rfc-editor.org/rfc/rfc8288).

Example `Link` header for a request to `?page=2&page_size=10` on a 42-item result set:

```
Link: </v1/metadata/doi:10.1162/qss_a_00292?page=3&page_size=10>; rel="next",
      </v1/metadata/doi:10.1162/qss_a_00292?page=1&page_size=10>; rel="prev",
      </v1/metadata/doi:10.1162/qss_a_00292?page=1&page_size=10>; rel="first",
      </v1/metadata/doi:10.1162/qss_a_00292?page=5&page_size=10>; rel="last"
```

Each comma-separated entry is a separate link. `rel="first"` and `rel="last"` are always present. `rel="next"` is omitted on the last page; `rel="prev"` is omitted on the first page.

The response body contains only the results for the requested page, in the same format as a non-paginated response (JSON array or CSV rows). When a [custom format](format-converters) is configured, pagination is delegated to the format converter because custom formats can change the number of entities in the output. The `Link` header is only generated when no custom format is active.

Invalid values (`page` without `page_size`, `page_size=0`, `page=-1`, non-integer values, `page` exceeding total pages) return HTTP 422.

Invalid built-in query parameters return HTTP 422 instead of being ignored or normalized. This applies to unsupported `format` values, malformed `json` transforms, unknown `require`, `filter`, or `sort` fields, malformed filters, invalid filter regexes, and malformed sort expressions.

## Combined example

```
/v1/metadata/doi:10.1162/qss_a_00292?require=author&filter=pub_date:>2020&sort=desc(pub_date)&format=csv
```

This removes rows without an author, keeps only those published after 2020, sorts by date descending, and returns CSV.

## Disabling built-in parameters

Operations or entire APIs can suppress built-in parameters with `#disable_params` in the spec file. When disabled, the parameter has no effect at runtime and does not appear in generated documentation.

```
#disable_params require,sort,format,json
```

Use `*` to disable all built-in parameters at once

```
#disable_params *
```

See the [spec file reference](01-spec-file.md) for placement and syntax.
