--- id: API-6 family: GR-API level: core profiles: [storage-api] posture: normative-target added: "1.0" changed: "1.0" source: https://flowdrop.io/spec/rules/gr-api/api-6 specification: FlowDrop Workflow Specification 1.0-draft licence: CC BY 4.0 --- # API-6 — Paging is clamped silently, and the clamped values are what is reported *GR-API (Part I) · level: core · profiles: storage-api · added in 1.0* ## The rule > **Normative.** This is the rule. > > 1. A paginated door caps `limit` at 100 and floors `offset` at 0. > > 2. Out-of-range paging is corrected, never refused: there is no 400 for it. > > 3. The corrected values are what the pagination block reports, so a caller that asked for 1000 and was served 100 is told 100 and its `has_more` arithmetic holds. > > 4. `total` is counted before pagination and under every filter the result carries, so a filtered page's total describes the filtered set and not the whole collection. ## What it means Out-of-range paging is corrected, not refused — there is no 400 for asking for too much or for a negative offset. But the correction is not silent in the sense of invisible: the values reported back are the ones actually used, so a caller who asked for far more rows than the cap allows is told the capped number, and its own arithmetic on `has_more` still holds. `total` is counted before pagination is applied, and under whatever filter the request carries. A filtered page's total describes the filtered set, not the whole collection — a search that matches nothing is an empty page with a `total` of zero, not the size of the unfiltered table. ## Example Asking for far more than the cap still gets a coherent, corrected answer. ```http title="A limit far above the cap" verdict="200 clamped" GET /api/flowdrop/workflows?limit=1000 {"pagination": {"total": 3, "limit": 100, "offset": 0, "has_more": false}} ``` A filter that matches nothing still gets a well-formed, empty page. ```http title="A search term matching no row" verdict="200 counted" GET /api/flowdrop/workflows?search=nothing+here {"pagination": {"total": 0, "limit": 50, "offset": 0, "has_more": false}} ``` `total` is the filtered count in both cases, never the size of the whole collection behind it. ## Related rules - Names: API-5 - Referenced by: API-5, STORE-15 --- Rule identifiers are permanent and are never renumbered. This specification carries no implementation status: each implementation publishes its own standing against these rules. Licensed CC BY 4.0.