org:view, shaping the tree and branches takes
org:configure, placing users on nodes takes org:assign.
The tree
Node types and the ladder they hang on:region → country → branch → team
→ agent. A branch may hang directly under a region, an agent under anything, and
any node may be a root. A branch node can be linked to a branch record
(branch_id, one node per branch) and a team node to a team (team_id).
Re-parenting is checked for cycles (409 CONFLICT, details.reason: cycle) and
re-validated against the ladder. Deleting a node with children is refused
(409 CONFLICT, details.reason: has_children) unless you pass cascade=true;
the response then lists every deleted_ids entry, since the database takes the
whole subtree and its memberships in one go.
Placement is reach
A membership (PUT …/members/{user_id}) is how a user gets team or branch
reach in the visibility engine: with visibility_scope: full they see the whole
subtree under that node, with own only their own records there. The same rules
narrow an API key’s reads to what its owner may see, so moving a subtree or a
member changes what both the UI and the API return for them. Role-level reach per
module is read from GET /v1/visibility-scopes.
A user’s branch_id (set on POST/PATCH /v1/users) is the branch they work
in; an org-node membership is where they sit in the tree. Both matter: the
branch on a record is matched against the user’s accessible branches, and the
record’s org_node_id against their subtree.
Branches
Deleting a branch is refused while anything still references it: the response carriesdetails.reason: in_use and details.references with counts of users,
org nodes, teams, leads, deals and accounts. Reassign or remove those first.
Every write records an auditlog row naming the API key that acted.