Saved Views

Store and share workspace layouts - board, table, calendar, timeline, and map views with their filters, sorting, grouping, and columns.


A saved view captures how a workspace is displayed: the layout (board, table, calendar, timeline, or map), plus the filters, sorting, grouping, and column settings applied on top of it. Members switch between views to see the same records through different lenses without re-configuring anything. In the API a saved view is a SavedView object, and it belongs to a workspace (Project).

Views are either personal (visible only to the member who created them) or shared (visible to everyone in the workspace). Any workspace member can create personal views; only OWNER and ADMIN members can create shared ones. The layout details live in the free-form viewConfig JSON, which the server validates against a fixed schema before storing.

POST https://api.blue.cc/graphql
X-Bloo-Token-ID: YOUR_TOKEN_ID
X-Bloo-Token-Secret: YOUR_TOKEN_SECRET
X-Bloo-Company-ID: YOUR_COMPANY_ID
X-Bloo-Project-ID: project_123

The X-Bloo-Project-ID header scopes requests to one workspace. Company and project headers accept either an ID or a slug. Header names are case-insensitive.

Operations

OperationGraphQLDescription
Create a saved viewcreateSavedView mutationAdd a view to a workspace. Documented below.
List saved viewssavedViews queryRetrieve the views in a workspace, with pagination.
Update a saved vieweditSavedView mutationChange a view’s name, icon, sharing, or viewConfig.
Delete a saved viewdeleteSavedView mutationPermanently remove a view from a workspace.

Three more mutations round out the surface but don’t have dedicated pages:

OperationGraphQLDescription
Reorder a viewupdateSavedViewPosition(id: String!, position: Float!): SavedView!Move a view to a new sidebar position.
Set workspace defaultsetWorkspaceDefaultView(projectId: String!, viewId: String): Project!Set a shared view as the workspace’s default; pass null for viewId to clear.
Set personal defaultsetUserDefaultView(projectId: String!, viewId: String): Boolean!Set the calling member’s default view for a workspace; null clears it.

Create a saved view

Use the createSavedView mutation to add a view to a workspace. The minimum is a name, a viewType, and a viewConfig object (which may be empty, {}). Everything else - an icon and whether the view is shared - is optional.

Request

The smallest call creates a personal board view with no extra configuration. An empty viewConfig: {} is valid; the layout falls back to defaults.

mutation CreateSavedView {
  createSavedView(
    input: { projectId: "project_123", name: "My Board", viewType: BOARD, viewConfig: {} }
  ) {
    id
    name
    viewType
    isShared
    position
  }
}

Parameters

CreateSavedViewInput

ParameterTypeRequiredDescription
projectIdString!YesID or slug of the workspace to create the view in. The caller must be a member of the workspace.
nameString!YesDisplay name. Must be non-empty and at most 100 characters.
viewTypeSavedViewType!YesThe layout. One of the SavedViewType values below.
viewConfigJSON!YesLayout configuration object. May be empty ({}). Validated server-side - see View configuration.
iconStringNoIcon identifier. At most 50 characters.
isSharedBooleanNotrue shares the view with all workspace members. Defaults to false (personal). Only OWNER / ADMIN may set true.

SavedViewType

ValueLayout
BOARDKanban-style board.
DATABASETable / spreadsheet grid.
CALENDARCalendar.
TIMELINEGantt-style timeline.
MAPGeographic map.

Response

{
  "data": {
    "createSavedView": {
      "id": "clm4n8qwx000008l0g4oxdqn7",
      "name": "My Board",
      "viewType": "BOARD",
      "isShared": false,
      "position": 65535
    }
  }
}

Returns

The mutation returns the created SavedView.

FieldTypeDescription
idID!Unique identifier for the view.
uidString!Short public identifier.
nameString!Display name.
iconStringIcon identifier, or null if none was set.
positionFloat!Ordering position in the sidebar. See Positioning.
isSharedBoolean!Whether the view is shared with all workspace members.
viewTypeSavedViewType!The layout.
viewConfigJSON!The stored configuration object.
createdByUser!The member who created the view.
projectProject!The workspace the view belongs to.
createdAtDateTime!When the view was created.
updatedAtDateTime!When the view was last updated.

Full example

A shared table view filtered to a tag, sorted by due date, grouped by a custom field, with two columns hidden.

mutation CreateSprintView {
  createSavedView(
    input: {
      projectId: "project_123"
      name: "Sprint Planning"
      icon: "layout-grid"
      isShared: true
      viewType: DATABASE
      viewConfig: {
        searchQuery: "launch"
        tagIds: ["tag_123"]
        tagMode: "or"
        sort: { type: "builtin", field: "duedAt", direction: "asc" }
        groupBy: { type: "customField", fieldId: "field_123" }
        hiddenColumns: ["field_456", "field_789"]
        pinnedColumns: { left: ["field_123"], right: [] }
      }
    }
  ) {
    id
    name
    icon
    viewType
    isShared
    position
    viewConfig
    createdBy {
      id
      fullName
    }
    project {
      id
      name
    }
    createdAt
  }
}

View configuration

viewConfig is a JSON object, but it is not free-form - the server validates it against a fixed schema and rejects unknown shapes. The whole object must serialize to under 50,000 bytes. Every key below is optional; an empty {} is valid and the layout uses defaults. Unrecognized keys are stored but ignored on read.

Filtering

KeyTypeDescription
searchQueryStringText to match records against. At most 1,000 characters.
assigneeIds[String]Restrict to records assigned to these user IDs. At most 100 entries.
assigneeModeStringHow to combine assigneeIds: "and" or "or".
tagIds[String]Restrict to records carrying these tag IDs. At most 100 entries.
tagModeStringHow to combine tagIds: "and" or "or".
dateStartStringStart of a date range. At most 1,000 characters.
dateEndStringEnd of a date range. At most 1,000 characters.
datePresetStringNamed relative range (e.g. a “this week” preset). At most 1,000 characters.
advancedFiltersJSONNested filter expression for complex queries. Loosely validated - only the overall size limit applies.

Sorting

sort is a single object (not an array), with all three fields required:

KeyTypeDescription
typeStringOne of "builtin", "custom", or "customField".
fieldStringThe field to sort by (e.g. "duedAt", or a custom field ID).
directionString"asc" or "desc" (lowercase).

Grouping

groupBy is an object with a required type:

KeyTypeDescription
typeStringOne of none, list, status, assignee, priority, date, tag, select, createdDate, customField, customDateField, customLookupField, referencedBy.
fieldIdStringCustom field ID to group by (used with customField / customDateField / customLookupField).
fieldNameStringHuman-readable field label.
modeStringFor date-based grouping: "actual" or "relative".

Columns

KeyTypeDescription
hiddenColumns[String]Column / field IDs to hide. At most 100 entries.
pinnedColumns{ left: [String], right: [String] }Column / field IDs pinned to the left or right edge; each side at most 100 entries.

Timeline

These keys apply when viewType is TIMELINE:

KeyTypeDescription
timelineZoomStringOne of day, week, month, quarter, year.
timelineDepDisplayStringDependency line display: always, selected, or hidden.
timelineShowCascadeBooleanWhether dependent records shift when a record moves.
timelineShowCriticalPathBooleanWhether to highlight the critical path.
timelineDateConfigobject{ startSource, endSource }, each one of createdAt, startedAt, duedAt, updatedAt, completedAt, or { customFieldId: String }.
viewType inside viewConfig

viewConfig may also carry its own viewType key, validated against the same SavedViewType set. This is separate from the top-level viewType argument, which is the one that determines the view’s layout. You can omit the nested key entirely.

Errors

CodeWhen
PROJECT_NOT_FOUNDThe projectId doesn’t exist, or the caller is not a member of the workspace.
FORBIDDENA non-OWNER / non-ADMIN member tried to create a shared view (isShared: true). Message: You are not authorized.

viewConfig validation failures are thrown as a plain ViewConfigValidationError, not an Apollo error, so the response carries no specific code (it surfaces as a generic server error). Validation rejects a viewConfig that isn’t an object, exceeds 50,000 bytes, a name that is empty or over 100 characters, an icon over 50 characters, or a malformed sort, groupBy, pinnedColumns, or timeline shape (see View configuration). The message describes the offending field, e.g. sort.direction must be 'asc' or 'desc'.

Permissions

  • Personal views (isShared: false, the default): any workspace member may create one.
  • Shared views (isShared: true): only members with the OWNER or ADMIN access level may create one. Others receive FORBIDDEN.

Positioning

New views are assigned a position of the last position in their scope plus 65535, or 65535 for the first view in that scope. Scope is per-workspace and split by sharing: a shared view is positioned after the last shared view; a personal view is positioned after the caller’s last personal view. Use updateSavedViewPosition to reorder afterward.