Skip to content

Org graphs

An org graph links Customer orgs: one identity in many orgs, parents over children, partners acting for clients, and resellers selling on.

A partner takes on a client

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.

FamilyWhat it does
MembershipsOne 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 childrenAn 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-upsA parent pays for its children on one bill with a statement line per child, and reads metrics, usage and the audit log across them
PartnersAn agency, accountant or managed provider acting for client orgs under a grant per client: admin, billing or support
Consolidated billingA partner pays for the clients it serves on one invoice, and each client still sees its own usage and receipts
ResellersAn 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 orgsTransfer 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 caseA 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.

definition.ts
17 lines
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.

Response
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.

ThingStatesWhat moves it
A membershipinvited, active, suspended, removedAn admin's invite, the person's accept, directory sync; a removal ends every session in that org
A parent linkproposed, accepted, detachedThe parent proposes, the child's admin accepts; a detach keeps the child's records and moves its billing back to it
A partner grantoffered, accepted, active, then revoked or expiredThe partner offers its scopes, the client's admin consents, and either side ends it
A resellerapplied, approved, selling, suspended, endedYou approve it, its connected account onboards on Stripe, and its customers stay on the product when it ends
A transfer, merge or splitproposed, consented, running, then done or haltedBoth admins consent; the records move while the orgs keep serving, and a halted move changes nothing
VerbWhat it does
Membership.switchChanges the org a session acts in
Org.link, Org.detachPuts an org under a parent, or takes it out
PartnerGrant.offer, PartnerGrant.revokeOffers a partner's scopes to a client, or ends them
Org.transfer, Org.merge, Org.splitMoves records, members and billing between orgs, with both admins' consent
Reseller.applyAsks 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.