Skip to content

Records and relationship access ​

DynamicObject record APIs now create, list, read, partially update, and soft-delete records. DynamicGroups now provide generated record tables/forms; see Query execution and groups.

All paths below start with /v1/organizations/{orgId} and use the API host. POST requires JSON, a session cookie, and X-CSRF-Token. Data permissions follow the selected organization role. Owner mode has full data access.

MethodPathPurpose
POST/objectsCreate with {objectTypeId,data:{...}}
GET/objects?objectTypeId={id}List authorized records
GET/objects/{id}Read one authorized record
POST/objects/{id}Partial update with {revision,data:{...}}
POST/objects/{id}Soft-delete with {revision,action:"delete"}

Successful reads/writes contain object (or objects for lists), with id, objectTypeId, schemaVersion, revision, and readable data. List requests accept limit (1–100, default 50) and after (the previous nextCursor). Results contain hasMore and nextCursor, with stable ascending ID ordering. No total count is returned. Relationship restrictions apply before pagination.

Values and schema ​

Use immutable field keys in data, with strict JSON types. For example:

json
{
  "objectTypeId": "<Student ObjectType ID>",
  "data": {"name": "Jane Smith", "grade": 5, "active": true}
}

Numeric strings and boolean strings are rejected. Required/default/option and numeric/text limits are enforced on every write. Date-time values require a valid timezone-bearing timestamp. Unknown fields return 422 with field errors; unauthorized field writes return 403. Read responses omit hidden fields, including on successful writes. Update/delete requests require the current revision; stale writes return 409.

The first successful record creation freezes an aggregate schema snapshot at version 1. Structural field changes then require explicit migration, even after records are retired. Label/help changes remain allowed. Legacy records are not automatically adopted. Query-backed options cannot accept non-null values until live option lookup and record-time validation are implemented.

Only linked records ​

On Permissions → Data & View Permissions, choose Only records linked to the member’s profile, then a matching relationship. The selected UserType must reference the profile ObjectType on the opposite side of that relationship. Grants apply to read/update/delete; related-only creation is unavailable.

For a Teacher role limited to assigned Students:

  1. Set Teacher as the UserType's profile ObjectType.
  2. Create a Teacher profile record and Student records using Owner mode.
  3. Bind the member account to its Teacher record.
  4. Connect authorized Student records to that Teacher record.
  5. Configure the Student data policy to use that relationship.

Profiles are explicitly bound by the owner, never inferred from email or record creator. Owners manage bindings and connections in Admin Panel → Records, or through these APIs:

MethodPathOwner-only request
GET/record-identities?userId={id}Inspect profile bindings and revisions
POST/record-identities{userId,objectTypeId,objectId,revision}; null objectId clears
GET/object-relationships/{id}/edgesList active connections; optional objectId/after/limit/includeRetired=1
POST/object-relationships/{id}/edges{sourceObjectId,targetObjectId,revision,action:"link"}
POST/object-relationships/{id}/edgesSame IDs with action:"unlink" and current revision

Use revision 0 for new bindings/connections. A profile record can belong to only one account, with one profile per account/ObjectType. Cardinality and same-organization endpoint types are enforced. Source cardinality means sources per target; target cardinality means targets per source. Restrict connections block record deletion; detach connections are retired with deletion. Owners can unlink dangling connections to retired endpoints if cleanup was interrupted.

Missing/retired profiles, missing bindings, removed links, expired memberships, or unassigned roles deny access. Unrelated detail/update/delete requests return 404. Switching roles uses the newly selected role's policies. Link/identity mutations remain Owner-only to prevent members from granting themselves access. Bounded multi-hop scopes and narrowing Group/View restrictions are supported; see the sections below.

Concurrent organization data/role mutations may return 409 PERMISSION_CHANGE_IN_PROGRESS; retry shortly. Operators must recover a stale fail-closed lock if a worker was forcibly killed. Writes have bounded embedded audit history and request IDs; histories are not exposed through record reads.

Records and summaries update ​

Owner Records, contextual anchor-record creation/deletion and permission-aware summary groups are implemented. See Records and summary groups. Authorized record search and prompted action record pickers are available. Multi-record creation remains planned.

Multi-hop record scope ​

Owner data-policy requests support recordScope: {mode:"path", path:[{relationshipId,from:"source"|"target"}, …]}. Paths have 1–4 continuous, typed, tenant-local steps ending at the selected UserType's profile ObjectType. The signed-in account's active profile binding is resolved automatically; ordinary record/query/group/View requests need no profile ID parameter. Existing all, profile, and related scopes remain supported.

All record reads, updates, deletions and aggregates use the resulting root-record restriction before pagination. Missing/retired profiles, links or intermediate records grant no access. Each resolution permits at most 500 traversed connections; overflow or execution-budget exhaustion returns 429 without partial results. Related fields still require independent read permissions. Standalone scoped Create remains denied; action creation can be explicitly granted as described below. See permission configuration.

Owner connection listings accept sourceObjectId and targetObjectId alongside existing pagination and includeRetired=1. Combining both filters retrieves the exact pair and its revision for the setup selectors. Mutations continue to require current revisions and enforce cardinality. Owner permission-member listings now include userId for profile-binding selection; this catalog remains Owner-only.

Binding overview ​

Owner-only GET /record-identities?overview=1 returns bindings, hasMore, and nextCursor. Optional limit (1–50 members, default 20) and membership-ID after paginate members without splitting their bindings. The existing GET /record-identities?userId=… remains available.

Rows combine assigned active UserTypes' expected profile types with actual active identity links, including additional links no assigned role requires. They include userId, email, memberStatus, userTypeNames, profile type/name, bound record/label, status (Bound/Missing/Unavailable/Not required), current revision and canUnbind. The tenant-local overview also includes removed members retaining active bindings. Responses are capped at 5,000 profile rows and 500 identity records per member; reduce the member page size for large profiles.

Use the existing revision-checked POST /record-identities with objectId:null to clear a binding. Owners may clear an existing active binding for an expired/removed member or unavailable account; establishing a binding still requires an active, unexpired member and active account. Clearing never grants access. Existing CSRF, tenant scoping, audit history and revision-conflict rules apply.

Current connection overview and replacement ​

Owner-only GET /record-connections returns connections, hasMore, and nextCursor. Optional relationshipId filters the whole dataset to an active tenant-local relationship. limit accepts 1–100 (default 50); after is an edge-ID cursor. Only active connections are returned. Rows include relationship/type names, source/target IDs and labels, revision, availability status, canModify, and canDisconnect. Unavailable endpoint records do not prevent cleanup of a stored pair under an active relationship definition.

Existing POST /object-relationships/{id}/edges additionally accepts:

json
{
  "action": "replace",
  "sourceObjectId": "<original source>",
  "targetObjectId": "<original target>",
  "revision": 1,
  "newSourceObjectId": "<replacement source>",
  "newTargetObjectId": "<replacement target>",
  "replacementRevision": 0
}

replacementRevision is 0 for a never-used pair, or the current revision returned by an exact-pair lookup with includeRetired=1. Replacement validates the original active pair, destination pair revision, active endpoint types/tenant, duplicates and cardinality before mutation. The original pair is excluded only from replacement's cardinality check. Stale/invalid/conflicting choices leave the original intact. Success retires the original pair and activates or revives the replacement, returning replaced:true, the replacement revision and originalRevision. Both audit events share an operation ID. Record data is not mutated.

Replacement runs under the existing organization mutation mutex. On standalone MongoDB it is fail-closed, not a multi-document transaction: the original is retired first so interruption may disconnect it but cannot leave conflicting active pairs. Review/reconnect through the Owner connection manager after the existing lock-recovery procedure if an operation is interrupted. Ordinary unlink requests require an actual tenant-local stored pair and current revision but can clean up connections with missing endpoints. Owner authorization and CSRF remain mandatory.

Action-only creation grants ​

Data policies accept boolean allowActionCreate (default false) and createRelationshipIds (default empty). Related/path policies may grant Create only when allowActionCreate:true; ordinary record/group creation still rejects unlinked records under those scopes. DynamicAction execution validates the complete proposed connections against the current profile scope before creating a pending record. Own-profile policies still reject Create.

createRelationshipIds must name active relationships connected to this ObjectType and requires Create. It authorizes only action-time creation connections, not generic member edge administration or relationship replacement. Group action placements also intersect group operations, writable bindings, per-cell eligibility, group-required fields, context/query constraints and View overrides. Record and policy revisions remain enforced.

Dynamic Tables — product guides and API reference.