Topology And Refs
The platform models tenants as a layered topology — relationship
boundaries and operating-account boundaries are separate first-class
concepts, not variants of one generic Account. Every identifier in
the public API is a canonical typed reference that makes that layering
visible directly on the wire.
This gives integrators four concrete advantages:
- Self-describing identifiers — you can tell at a glance what a value refers to, in code review, in logs, and in support tickets, without consulting a separate type field.
- End-to-end traceability — the same ref appears unchanged in requests, responses, events, approvals, and audit. One token grep in your logs trails a single entity across the whole platform.
- Type-safe scoping — operations that expect a topology boundary reject account refs, and vice versa. A whole class of wrong-scope-paste bugs disappears at request validation time.
- Stable across lifecycle — a ref does not change when a resource is suspended, reactivated, or moved between rails. Reconciliation pipes and external mappings stay correct over the resource's entire life.
The Topology Graph
Four canonical resources form the tenant graph:
Enterprise— root customer relationship boundary (the tenant itself)Master Account— primary operating account anchored to an enterprise; balances and tenant-level execution live hereClient— subordinate relationship boundary inside an enterprise; represents a downstream business subjectClient Account— subordinate operating account inside a client; balances and client-scoped execution live here
The graph layers two parallel ideas:
- Relationship layer —
Enterprise → Client[] - Operating-account layer —
Enterprise → Master Account[]andClient → Client Account[]
Two disciplines make this layering powerful:
- Relationship boundary is not the same as operating account.
Clientrepresents who you are doing business with;Client Accountis where money for that business actually moves. They are separate resources with separate identifiers, separate lifecycle, and separate audit trails. - One-to-many by design. An enterprise can hold multiple master accounts; a client can hold multiple operating accounts. The contract treats this as the canonical shape, not as a future extension — your integration code can rely on the layering being there.
The benefit shows up in lifecycle, audit, and reporting: you can see which client account moved money under which client under which enterprise, without reverse-engineering the structure from a flat parent pointer.
For balance and execution semantics inside this graph, see Accounts.
scope_ref — How Topology References Appear In API Calls
In the public API, a TopologyRef travels under the name scope_ref.
It appears in two places:
- Query parameter on every list operation that returns resources scoped to a
perimeter (
GET /users,GET /clients,GET /roles, etc.) - Request body field on create operations that place a new resource inside a
perimeter (
POST /users,POST /clients,POST /roles, etc.)
Finding your scope_ref
After issuing an access token (OAuth client credentials), the bearer token is a
JWT. Decode the payload — the b2b2x:tenant_ref claim holds your topology
reference:
Pass that value verbatim as scope_ref:
Which ref format each endpoint accepts
Different endpoints constrain which topology level is valid:
scope_ref format |
Accepted by |
|---|---|
enterprises/{uuid} |
users, clients, roles, approvals, capabilities, master-accounts, identity-providers, events, webhook-subscriptions, withdrawal-destinations, role-assignments, policy-rules |
clients/{uuid} |
client-accounts, role-assignments, eligible-crypto-networks, eligible-payout-methods, webhook-subscriptions |
The pattern in the parameter schema tells you exactly which formats are accepted
for each endpoint — a mismatch returns a 400 validation error immediately.
Mental Model
Three ref kinds cover the whole API:
- TopologyRef — ownership, governance, and perimeter
- AccountRef — financial execution and balance boundaries
- ResourceRef — broader pointers used by helper surfaces (events, approvals, audit) that need to reference an existing object without treating it as a scope itself
Pick the kind based on what the request is acting on. The platform validates the kind before the request even reaches business logic, so mismatches surface as clean validation errors instead of as obscure runtime failures.
TopologyRef
TopologyRef identifies a topology boundary:
enterprises/{uuid}clients/{uuid}
Use TopologyRef whenever a request needs a parent, owner, or
governance boundary — creating downstream resources, scoping a list,
applying a policy, granting a role assignment.
The benefit is that every governance-relevant call carries the same shape of identifier, so policy and access logic resolve uniformly across resource families.
AccountRef
AccountRef identifies a financial operating account:
master-accounts/{uuid}client-accounts/{uuid}
Use AccountRef for financial execution inputs:
- withdrawals
- conversions
- internal transfers
- ramp sessions
The benefit is that the same account ref drives execution and balance
visibility — submit a withdrawal against client-accounts/55…, then
read balances on client-accounts/55…, then trace the resulting event
on client-accounts/55…. One identifier, one entity, one trail.
ResourceRef
ResourceRef is the broader reference shape used by audit, event, and
helper surfaces — the ones that need to point at an existing resource
without implying that the target is itself a topology or execution
boundary.
Concrete examples:
- an event payload referencing the operation it describes
- an approval case referencing the resource whose change is under review
- an audit entry referencing the actor or scope a decision was about
This keeps helper surfaces flexible (they can refer to any first-class
object) without diluting the meaning of TopologyRef and AccountRef
in the parts of the API where scope semantics matter.
How This Appears In The API
Request Body
{
"parent": "enterprises/11111111-1111-4111-8111-111111111111",
"external_id": "crm-248",
"display_name": "Northwind Treasury"
}Request Body
{
"account_ref": "client-accounts/55555555-5555-4555-8555-555555555555",
"amount": {
"value": "250.00",
"currency": "USD"
},
"rail": "fiat"
}