Skip to main content
View as Markdown

Filtering, Sorting & Pagination

GET /api/tables/:tableId/records returns a paginated envelope and accepts a rich set of query parameters to paginate, sort, filter, select fields, group, and aggregate records — so you can shape large datasets without writing custom endpoints. Every parameter is optional; combine them freely.

GET /api/tables/tasks/records?limit=10&offset=0&sort=priority:desc,name:asc&fields=id,name,status

The response is always the list envelope (never a bare array):

{
  "records": [{ "id": "1", "fields": {} }],
  "pagination": { "total": 128, "limit": 10, "offset": 0 }
}

Query parameter reference

Parameter Description Example
limit Maximum records to return ?limit=20
offset Number of records to skip ?offset=40
page Page number (1-indexed) — alternative to offset ?page=3
sort Sort field(s) and direction ?sort=name:asc,created_at:desc
order Sort order (asc/desc) for a single-field sort ?sort=name&order=desc
fields Comma-separated field names to include ?fields=id,name,status
filter Filter expression (JSON) ?filter={"status":"active"}
view Apply a saved view configuration ?view=2
groupBy Group records by a field ?groupBy=status
aggregate Aggregation functions ?aggregate=sum:amount,count:id
q Free-text search query ?q=invoice
format raw (default) or display field values ?format=display
timezone IANA timezone for date display formatting ?timezone=Europe/Paris
includeDeleted true to include soft-deleted rows; only for trash-only ?includeDeleted=true

Pagination

Two equivalent paging styles are supported. Use limit + offset for cursor-style scanning, or limit + page for page-numbered UIs. pagination.total is the count of all matching rows (independent of the page), so a client can compute the page count as ceil(total / limit).

GET /api/tables/tasks/records?limit=20&offset=40   # rows 41–60
GET /api/tables/tasks/records?limit=20&page=3       # rows 41–60 (1-indexed)

Sorting

Sort by one or more fields, each with a direction, using field:direction segments separated by commas. The leftmost field is the primary sort key.

GET /api/tables/tasks/records?sort=priority:desc,name:asc

For a single sort field you may instead split the field and direction across sort and order (?sort=name&order=desc). The field:direction form is preferred because it composes cleanly for multi-key sorts.

Field selection

Request a subset of columns with fields. This trims the response payload — useful for list views that only render a few columns. Fields the caller cannot read are omitted regardless of whether they appear in the fields list.

GET /api/tables/contacts/records?fields=id,name,status

Filtering

Pass a JSON filter expression in the filter parameter. A flat object filters by equality on each key:

GET /api/tables/tasks/records?filter={"status":"active"}

For richer conditions, filters use the same structured form as saved views — a tree of and/or groups whose leaves are { field, operator, value } conditions:

filters:
  and:
    - field: status
      operator: in
      value: [todo, in_progress]
    - field: priority
      operator: equals
      value: high

Conditions name a field, an operator (e.g. equals, in, greaterThan), and a value. Operators are resolved per field type.

Grouping & aggregation

groupBy partitions records by a field's value; aggregate computes summary functions. Combine them to produce grouped roll-ups (e.g. total amount per status).

GET /api/tables/orders/records?groupBy=status
GET /api/tables/orders/records?aggregate=sum:amount,count:id,avg:quantity

Each aggregate entry is function:field — supported functions include sum, count, avg, min, and max. When paired with groupBy, aggregates are computed per group.

Saved views

A view (?view=2) applies its stored filter, sort, and field configuration server-side. Explicit query parameters layer on top of the view, letting a client further narrow a base view without redefining it.

tables:
  - id: 1
    name: tasks
    views:
      - id: 2
        name: Active Tasks
        filters:
          and:
            - field: status
              operator: in
              value: [todo, in_progress]
        sorts:
          - field: priority
            direction: desc

Including deleted records

By default, soft-deleted rows are excluded. Use includeDeleted=true to merge active and deleted rows, or includeDeleted=only for a trash-only view. See Soft Delete & Restore for the full recovery workflow.