SG Ground Truth

pages

A page's layout is the PageSetting row whose user is null; settings_json reads back as decoded JSON and body/list_content settings.columns is the column list. Every filter on it is ignored.

API

Q What is a page over REST, and can a client read a page's settings and its visible columns?

Endpoint GET /entity/pages ; POST /entity/page_settings/_search ; GET /schema/PageSetting/fields

Docs claim Silent. The REST docs list no page endpoint and describe no layout format.

Actual

/schema matched 3 of 114 type names: Page, PageHit, PageSetting
Page 24 fields, PageHit 5, PageSetting 6 (page, user, settings_json, ...); /schema/DisplayColumn -> 404 "Entity type 'DisplayColumn' does not exist."

GET /entity/pages paged                       1217   project set 1092   project null 125
_search [["project","is",null]]                 125   GET filter[project.Project.id]=<id> -> 59
GET filter[project]=null -> 400  API read() Page.project expected [Hash, ... NilClass] data type(s) but got String: "null"
_summarize record_count, no filter             2576   against 1092 over 22 projects + 125 null = 1217

/schema/PageSetting/fields/settings_json data_type "text"; returned decoded, never as a string
1217 of 1217 listed pages have >=1 PageSetting, the 125 site-level ones included;
  (settings_json shape, user set) -> {(object, false): 1219, (array, true): 27}

one shared PageSetting (user null), page_type "canvas", entity_type "Shot", 126 widgets in the tree:
  /                   SG.Widget.Canvas.Page
  /body               SG.Widget.EntityQuery.EntityQueryPage  settings=[entity_type,filters,grouping,mode,sorts,pivot_grouping,formatting_rules,...]
  /body/list_content  SG.Widget.NewGrid                      settings=[columns,column_widths,column_display_names,records_per_page,...]
  body.settings  entity_type "Shot"  mode "list"  sorts [{"column":"code","direction":"asc"}]
                 grouping [{"column":"sg_sequence","method":"exact","direction":"asc"}]
                 filters {"logical_operator":"and","conditions":[...{"path":"sg_status_list","relation":"is","values":["wtg"],"active":"true"}...],"filter_name":"<saved filter>","filter_id":2}
  list_content.settings.columns ["image","sg_status_list","code","sg_sequence","description","created_by"]
GET /entity/shots?fields=<those columns verbatim> -> 200  attributes [code,description,image,sg_status_list]  relationships [created_by,sg_sequence]
GET /entity/shots?fields=code,zzz_not_a_field -> 200  attributes [code]   (unknown name dropped, no error)

a per-user row is an array of patches, not a tree, 27 of 27 user-owned:
  [{"spec_path":"body|list_content","settings":{"columns":[...],"column_widths":{...}}}]

PageSetting baseline 30145. contains "ZZZNOPE" 30145, is null 30145, is_not null 30145,
  starts_with "ZZZNOPE" 30145, in ["ZZZNOPE"] 30145; control [["page","is",null]] -> 26372
Page.name    -> 400 ... Valid relations: ["contains","not_contains","is","is_not","starts_with","ends_with","in","not_in"]
Page.project -> 400 ... Valid relations: ["is","is_not","name_contains","name_not_contains","name_is","type_is","type_is_not","in","not_in"]

Teaches

Three types answer the question, and a page's configuration is split across two of them.

type what it holds how a client reaches it
Page the page itself: name, page_type, entity_type, project, ui_category, system_owned GET /entity/pages?fields=...
PageSetting the layout, in settings_json _search on page is {"type":"Page","id":N}
PageHit one row per view, page and user only GET /entity/page_hits

There is no DisplayColumn type, and Page has no field naming a column.

  • A site-level page is a Page whose project is null, and nothing else about it differs. Both kinds read from the same endpoint, both hold PageSetting rows of the same shape, and both take the same filters.
  • The two are told apart by project alone, so filter[project.Project.id]=N returns a project's pages and [["project","is",null]] returns the site-level ones. Send the string "null" to the flat filter and it 400s with got String: "null"; the operator wants a real null.
  • PageSetting.settings_json is text in the schema and decoded JSON in the response, so parse nothing.
  • Two shapes come back under one field: an object is the page's shared layout and its user is null, an array is one user's override and its user is set. Read [["page","is",{...}],["user","is",null]] to get the shared one and ignore the rest, or a personal column order will read as the page's.
  • The shared layout is a widget tree of {type, settings, children}. children.body.settings holds entity_type, mode, sorts, grouping and filters; children.body.children.list_content.settings holds columns in display order, plus column_widths and column_display_names.
  • The override array is [{spec_path, settings}], where spec_path is that same tree path with | between the segments, so body|list_content patches the grid.
  • columns are schema field names, usable in ?fields as they stand, and a dotted path such as created_by.HumanUser.email appears among them.
  • Some are stale or web-only: on the probed site, 5 of the 21 list pages in one project named a column absent from that type's /schema/<Type>/fields. ?fields answers 200 and drops a name the type does not have, so a stale column costs a missing key rather than an error. Check the list against /schema/<Type>/fields to know which columns you lost.
  • filters is the web condition tree (path, relation, values, logical_operator), not the _search array of probe 017. The names line up, so a converter is a walk over conditions, but the tree also holds active, filter_name and filter_id for a saved filter, and a top_level_project_filter condition that duplicates the project scope.
  • Every filter on settings_json is accepted and ignored. On the probed site all 30145 rows come back for contains "ZZZNOPE", for is null and for is_not null alike, while [["page","is",null]] on the same type returns 26372, so the endpoint filters fine and the field does not. Never search layouts server-side; page the rows and inspect them yourself.
  • _summarize disagrees with the listing on Page. On the probed site an unfiltered record_count returned 2576 against 1217 rows actually paged, while the same count filtered by project agreed exactly, summing to 1217 over 22 projects plus 125 project-null. Count pages by summing per-project and per-null, never with one unfiltered call.
  • Page and PageSetting filter and sort like any other type: the bogus-operator 400 enumerates the normal relations for each field's data type, and sort on a name that is not a field is accepted at 200 and ignored.

Every entry on this site is the output of a probe in probes/. The corpus is generated by running those probes against a live Flow Production Tracking site, not written from memory.

Not affiliated with or endorsed by Autodesk. Flow Production Tracking is their product; this is an independent record of how its REST API answers.