Record page payload — POST /api/v1/data/{object}/{id}/page. Reference for RecordPageApprovals and 10 more: every property with its type and default.
Record page payload — POST /api/v1/data/{object}/{id}/page.
One request that answers everything a record page asks of the server when it
opens: the record (with the lookups it names resolved), the count and first
rows of every related list the page draws, the caller's field projection of
the record, the approval state that locks it, and the record-grained access
verdicts its header actions are gated on.
The request NAMES the parts. Which related lists a page draws (their order,
their declared scope, which of them the reader may see) is the page's own
derivation, so the page sends the lists and the server answers each one; the
server never derives a list of its own. What the server owns is the parent
condition: each list is the child records whose field points at this
record, compiled to the field's arity, and AND-composed with the list's
declared filter — a declared filter can only narrow it.
Every part is the answer of the read it replaces, asked as the same caller:
the record is GET /data/{object}/{id}, a related list is
GET /data/{child} with that filter and $count, fieldAccess is
GET /data/{object}/{id}/field-access, explain is
POST /security/explain with the record id, and approvals is
GET /approvals/requests for the record plus
GET /approvals/records/{object}/{id}/lock. Object permissions, row-level
security, sharing and field-level security therefore apply exactly as they
apply to those reads. A part whose read refuses carries that refusal in place
of an answer — a related list the caller may not read carries neither a
count nor rows — and the other parts are answered. A record the caller
cannot read refuses the whole request with the record read's own answer, so
no part discloses a record the caller could not open.
The record's approval requests the caller may see, as GET /approvals/requests lists them for the record; empty when the deployment runs no approval service.
lock
{ locked: boolean } | null
✅
Whether a locking approval holds the record; null when the deployment answers no lock.
The composed row filter the caller would be served with — the machine artifact behind the prose (null = unrestricted). Two shapes mean zero rows — { id: "__deny_all__" } and the fail-closed RLS denial (__rls_deny__ plus a colon and a UUID-shaped suffix, which can also ride inside an $and composite) — so a consumer pattern-matching this payload alone must match both; the decision itself is allowed plus the rls layer verdict.
Row-level verdict for the specific record; set only for singular record-grained requests. An id the asker (the caller of explain) cannot read answers as missing, like a filtered, deleted or never-existed id: visible false, decidedBy omitted. Explaining another principal, the asker cannot read an id its own by-id read finds no row for or refuses; a principal explaining itself cannot read an id its read finds no row for.
ADR-0095 D2 posture rung — PLATFORM_ADMIN crosses the tenant wall where object posture permits; TENANT_ADMIN sees all rows in the org; MEMBER gets business RLS; EXTERNAL (an external organization member) reaches explicit grants only — shares, sharing rules, and grant RLS — never the OWD baseline.
The relationship field on the child object that points at this record (a lookup or master-detail field referencing the page's object). The list is the child records whose field holds this record's id.
filter
any
optional
The list's own declared scope, in the filter syntax GET /data/{object} accepts. AND-composed with the parent condition, so it can only narrow the list. A filter that syntax refuses refuses the whole request (a located 400 at related.N.filter) before anything is read.
top
integer
✅
How many of the list's first rows to return with its count; 0 returns the count alone.
sort
{ field: string; order: Enum<'asc' | 'desc'> }[]
optional
The order of the list's first rows, as GET /data/{object} orders them by $orderby. Absent for the default order.
The relationship field on the child object that points at this record (a lookup or master-detail field referencing the page's object). The list is the child records whose field holds this record's id.
filter
any
optional
The list's own declared scope, in the filter syntax GET /data/{object} accepts. AND-composed with the parent condition, so it can only narrow the list. A filter that syntax refuses refuses the whole request (a located 400 at related.N.filter) before anything is read.
top
integer
✅
How many of the list's first rows to return with its count; 0 returns the count alone.
sort
{ field: string; order: Enum<'asc' | 'desc'> }[]
optional
The order of the list's first rows, as GET /data/{object} orders them by $orderby. Absent for the default order.
Fields the caller may read on this object. Reads are judged row-blind, so this equals the object-wide read projection
editable
string[]
✅
Fields the caller may write on this record, as field-level security judges an update of the stored row: a row-conditioned field permission locks a field only on the rows its condition names. A field absent here is refused by the write gate. The object grant, the record's row-level write scope (sharing, row-level security, ownership; see writable) and a field's own rules (readonly, computed types) are not part of it
writable
boolean
✅
Whether the caller may update this record at all, judged by the write gate on the stored row: the object's edit permission, record sharing and ownership, row-level security, and a parent record's edit access for a record controlled by its parent. False means an update that leaves the record as it is stored is refused: either the caller may not edit this record, or the stored record fails a row-level security check that every save must satisfy, which a save moving the checked value back inside that check can still pass. True does not promise that a save succeeds: a pending approval that locks the record, conditional read-only and validation rules on the values sent, a data source that refuses writes, the platform's own rules for its own records (comments, attachments, mail messages, approval requests) and an object the API serves read-only are judged when the record is saved
The record's approval requests the caller may see, as GET /approvals/requests lists them for the record; empty when the deployment runs no approval service.
lock
{ locked: boolean } | null
✅
Whether a locking approval holds the record; null when the deployment answers no lock.