# Topology And Refs

> Layered tenant topology (Enterprise, Master Account, Client, Client Account) and the typed reference system that identifies each layer in the API.

Source: https://business-api-docs.youhodler.com/docs/concepts/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.

> **Practical rule:** If a call changes or reads financial activity, prefer `AccountRef`. If a call creates, scopes, or governs tenant relationships, prefer `TopologyRef`.

## 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 here
- **`Client`** — subordinate relationship boundary inside an
enterprise; represents a downstream business subject
- **`Client 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[]` and
`Client → Client Account[]`

Two disciplines make this layering powerful:

- **Relationship boundary is not the same as operating account.**
`Client` represents who you are doing business with;
`Client Account` is 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](/docs/concepts/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:

```json
{
  "sub": "service-accounts/...",
  "b2b2x:tenant_ref": "enterprises/c78778b9-b517-4c7b-8393-9db034ab5708",
  "b2b2x:principal_kind": "service_account",
  ...
}
```

Pass that value verbatim as `scope_ref`:

```
GET /users?scope_ref=enterprises/c78778b9-b517-4c7b-8393-9db034ab5708
```

### 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 — application/json**
```json
{
  "parent": "enterprises/11111111-1111-4111-8111-111111111111",
  "external_id": "crm-248",
  "display_name": "Northwind Treasury"
}
```
**Request Body — application/json**
```json
{
  "account_ref": "client-accounts/55555555-5555-4555-8555-555555555555",
  "amount": {
    "value": "250.00",
    "currency": "USD"
  },
  "rail": "fiat"
}
```
