Skip to main content

Organizations are tenants

Your organization is a tenant of 4D. Your API key is bound to it, your data lives inside it, and isolation is enforced at the database layer with row-level security - not just in application code. There is no cross-tenant read path: a partner API call can only ever see its own organization’s rows. Everything in these docs is scoped by that boundary: your members, your events, your XP economy, and your members’ consent records all belong to your tenant.

Multi-tenancy for multi-team organisations

4D is multi-tenant by design, and that extends to partners who are themselves more than one team. A multi-team organisation - a club group, a league, a federation with several sides - can run each team as its own tenant: separate API keys, separate member rolls, separate XP economies, tiers, and consent scopes, with no data bleed between them. Because identity is two-level, this stays friendly for the fan: one person who follows two of your teams is still one 4D user holding a membership in each tenant, with a single wallet and sign-in. Each team sees only its own membership; the platform handles the rest.

Bespoke integrations

The standard surface - the REST API, the engagement SDK, and bulk import - covers most integrations. When you need a private event surface, a partner admin can create and publish a private module, then install it for the owning organization. See Publish a private module for the complete REST path. A private module has an owning organization. It is visible and installable only to that organization, while a module without an owner is a platform or vendor module visible to every organization. Module authoring uses an admin session; an org_ key authenticates a service identity for partner reads and cannot publish a module or mint another key. The module declares its native event types and payload schemas. Canonical event types belong to the platform. At publish time, the manifest must fit the platform module contract; a manifest that does not fit is rejected and remains in draft. During ingest, native payloads and their mapped canonical payloads are checked again before a canonical event is emitted.