Subaccounts & X-Org-Id
Iron is multi-tenant by subaccount. Each subaccount (an “org”) owns its own data: contacts, conversations, pipelines, staff, agent config, connectors, and numbers. Nothing is shared across tenants.
The X-Org-Id header
Section titled “The X-Org-Id header”To act inside a specific subaccount, send its org UUID in the X-Org-Id header:
X-Org-Id: 11111111-2222-3333-4444-555555555555The API validates this against your crm.org_members rows:
- If you are a member of that org, the request acts inside it.
- If you are not a member, the API returns
403 Forbidden— and it never leaks whether the org exists. - If the header is malformed (not a UUID), the API returns
400.
If you omit X-Org-Id, the API resolves your earliest-joined org as the acting org.
The org hierarchy
Section titled “The org hierarchy”Orgs form a parent/child hierarchy. An agency org can have client subaccounts beneath
it (via the parent_org_id chain). This hierarchy drives:
- RLS scoping — at the database level, the acting org sees itself plus its direct children.
- “View as client” impersonation — an admin can mint a time-boxed token to act inside one
of their own subaccounts. The audit trail always records the real admin’s identity, even
under impersonation. See
POST /impersonate. - Agency-only endpoints — cross-account reports, rate cards, and rebilling are restricted to the agency org.
Org context in handlers
Section titled “Org context in handlers”Internally, every request resolves an OrgContext carrying:
user— the authenticated Supabase user.org— the resolved acting org.member— the caller’s membership row (role, client flag, data-scoping flags).
Roles and permission sets gate what a member can do; client members get a restricted, data-scoped view. See The Operator Model.