Org graphs
Open in
An org graph links Customer orgs: one identity in many orgs, parents over children, partners acting for clients, and resellers selling on.
Each link is a grant the client's admin consents to, and either side ends it. Filled: what the client sees.
Orgs above, beside and below each other
Every org in the graph is still one Customer org, with its own Namespace, records and audit log.
| Family | What it does |
|---|---|
| Memberships | One identity holds memberships in many orgs, each with its own Roles; a session carries the org it acts in, and switching changes nothing else |
| Parents and children | An org over its children, as deep as orgs.depth allows. Children inherit sign-in policy, factors, retention and Roles, and their admins tighten them only |
| Roll-ups | A parent pays for its children on one bill with a statement line per child, and reads metrics, usage and the audit log across them |
| Partners | An agency, accountant or managed provider acting for client orgs under a grant per client: admin, billing or support |
| Consolidated billing | A partner pays for the clients it serves on one invoice, and each client still sees its own usage and receipts |
| Resellers | An org that sells the product to its own customers in its own brand, at its own price above your floor, on its own connected Stripe account |
| Moves between orgs | Transfer a child to another parent, merge two orgs into one, or split part of an org into a new one, each a Verb both admins consent to |
| Sharing one case | A cross-org grant still lets two unrelated orgs work one case, with nothing copied |
Each act through a link is recorded twice: in the acting org's log as "acted for", and in the client's as "acted by". A client's admin reads every one.
Example
Customers may nest orgs three deep, agencies may act as admin and billing for their clients, and resellers sell at no less than the floor.
import { define } from 'apis.dev'
/** Deals for each Customer, kicked off when won. */
export default define({
name: 'pipeline', domain: 'pipeline.apis.dev',
Company: { name: 'string', domain: 'url!#', deals: '<-Deal.company' },
Deal: {
title: 'string', amount: 'decimal(12, 2)', company: '->Company.deals',
stage: { open: [], qualify: 'opened', win: 'qualified', lose: ['opened', 'qualified'] },
},
orgs: {
depth: 3, // a group, its regions, their teams
partners: ['admin', 'billing'], // an agency may set up and pay for a client
resellers: { floor: 39 }, // the least a reseller charges a month
},
offer: { Team: { month: 49, seats: 5, seat: 9 }, 'Deal.open': 0.001 },
})An agency's member lists the orgs it may act in: its own, and each client by its grant.
HTTP/1.1 200 OK
Content-Type: application/ json
X-Cost: price= 0, currency= "USD"
X-Request-Id: req_8d3b6e10f2a94c7e5b01
{
"items": [
{ "id": "org_northwind", "role": "admin", "via": "member" },
{ "id": "org_acme", "via": "partner", "grant": ["admin", "billing"] },
{ "id": "org_globex", "via": "partner", "grant": ["billing"] }
],
"total": 3
}That is GET /orgs on the product's own API, listOrgs over MCP and pipeline orgs list in the CLI.
Links and moves, state by state
Every link and move is a Verb on the product's API, MCP server and CLI.
Each writes its Event, so PartnerGrant.revoked or Org.merged reaches a Watch like any other.
| Thing | States | What moves it |
|---|---|---|
| A membership | invited, active, suspended, removed | An admin's invite, the person's accept, directory sync; a removal ends every session in that org |
| A parent link | proposed, accepted, detached | The parent proposes, the child's admin accepts; a detach keeps the child's records and moves its billing back to it |
| A partner grant | offered, accepted, active, then revoked or expired | The partner offers its scopes, the client's admin consents, and either side ends it |
| A reseller | applied, approved, selling, suspended, ended | You approve it, its connected account onboards on Stripe, and its customers stay on the product when it ends |
| A transfer, merge or split | proposed, consented, running, then done or halted | Both admins consent; the records move while the orgs keep serving, and a halted move changes nothing |
| Verb | What it does |
|---|---|
Membership.switch | Changes the org a session acts in |
Org.link, Org.detach | Puts an org under a parent, or takes it out |
PartnerGrant.offer, PartnerGrant.revoke | Offers a partner's scopes to a client, or ends them |
Org.transfer, Org.merge, Org.split | Moves records, members and billing between orgs, with both admins' consent |
Reseller.apply | Asks to resell the product, with the price and brand the reseller sells under |
What admins, partners and resellers meet
- A group's admin. One sign-in policy for every child org, one bill with a line per child, and metrics across all of them.
- A child's admin. Its own members, Roles and records, inside the limits its parent sets.
- An agency. Every client in one switcher, acting only within each client's grant, with one invoice for the clients it pays for.
- A client. A grant it can read and revoke, and each act an agency made in its own audit log.
- A reseller. The product under its own brand and price, its customers' bills on its own Stripe account, and a sales record of its own.
Every org keeps its own records while links let people, partners and resellers act across them, each by a grant the other side can end.
Sign-in and sessions
How every principal proves who it is: sign-in methods, sessions, publishable keys, second factors and step-up, recovery, and agents on the access ladder.
Model and records
Each Customer's Things, with their Relationships, state, history, files and content, and the search, views and metrics rebuilt from them.