Quickback Docs

Views API

Query named field projections with role-based access control.

Views provide named column projections that limit which fields are returned in API responses. Each view can have its own access control, and all security pillars (firewall, masking) still apply.

Endpoint

GET /api/v1/{resource}/views/{view-name}

Example

Given this definition:

export default defineTable(customers, {
  views: {
    summary: {
      fields: ['id', 'name', 'status'],
      access: { roles: ['owner', 'admin', 'member'] },
    },
    full: {
      fields: ['id', 'name', 'email', 'status', 'ssn', 'internalNotes'],
      access: { roles: ['owner', 'admin'] },
    },
  },
  // ...
});

Request

curl /api/v1/customers/views/summary \
  -H "Authorization: Bearer <token>"

Response

{
  "data": [
    { "id": "cust_001", "name": "Acme Corp", "status": "active" },
    { "id": "cust_002", "name": "Widget Inc", "status": "pending" }
  ],
  "view": "summary",
  "fields": ["id", "name", "status"],
  "pagination": {
    "limit": 50,
    "offset": 0,
    "count": 2
  }
}

Only the fields specified in the view definition are returned. Requesting the full view with a member role returns 403.

Query Parameters

Views support the same query parameters as the list endpoint:

ParameterDescriptionDefault
limitNumber of records to return (1–100)50
offsetNumber of records to skip0
sortField to sort bycreatedAt
orderSort direction (asc or desc)desc
{field}Filter by exact value
{field}.gtGreater than
{field}.gteGreater than or equal
{field}.ltLess than
{field}.lteLess than or equal
{field}.neNot equal
{field}.likePattern match (SQL LIKE)
{field}.inMatch any value in comma-separated list

Examples

# Paginated with sorting
GET /api/v1/customers/views/summary?limit=10&offset=0&sort=name&order=asc

# With filters
GET /api/v1/customers/views/summary?status=active&name.like=%25Corp%25

# Combined
GET /api/v1/customers/views/summary?status.in=active,pending&sort=name&order=asc&limit=25

Security

All security pillars apply to view endpoints:

  1. Authentication — Required (401 if missing)
  2. Firewall — Organization/user isolation applied to all results. Only records the user owns or has access to are returned.
  3. Access — Per-view role check. Each view can require different roles.
  4. Masking — Applied to all returned fields. If a masked field is in the view's field list, the masking rules still apply based on the user's role.

Access Control Per View

Different views can require different permission levels:

views: {
  // Available to all org members
  summary: {
    fields: ['id', 'name', 'status'],
    access: { roles: ['owner', 'admin', 'member'] },
  },
  // Admin-only view with sensitive data
  full: {
    fields: ['id', 'name', 'email', 'ssn', 'internalNotes'],
    access: { roles: ['owner', 'admin'] },
  },
}

A member requesting the full view receives:

{
  "error": "Insufficient permissions",
  "layer": "access",
  "code": "ACCESS_ROLE_REQUIRED",
  "details": { "required": ["admin"], "current": ["member"] }
}

Masking in Views

Masking is applied after field projection. If your masking config hides ssn from non-admins:

masking: {
  ssn: { type: 'ssn', show: { roles: ['admin'] } },
}

A member requesting a view that includes ssn will see the masked value (e.g., *****1234), while an admin sees the full value.

See Also

On this page