> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fourdos.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Tenants and members

> One person, one 4D identity - a member of each organization they engage with

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

## Users and members: a two-level identity

4D separates *who a person is* from *their relationship with your
organization*:

* A **user** is a person's single, global 4D identity, keyed by email
  (matched case-insensitively). Core profile fields - name, country, date of
  birth, locale - live here, along with their wallet.
* A **member** is that user's relationship with one organization: your
  `external_id` for them, their role, their status (`active`, `locked`,
  `removed`), and when they joined.

One person engaging with three 4D organizations is one user with three
memberships. When you `POST /v1/users` with an email that already has a 4D
account, the platform doesn't create a duplicate - it **attaches** the
existing user to your organization as a new member. Your view of them is your
membership plus their profile; other organizations' relationships with the
same user are invisible to you.

Two consequences worth designing around:

* **`external_id` is yours.** It's unique per organization, so you can address
  members by the id your own systems already use.
* **Age is derived, never stored.** The API returns a coarse `age_band`
  computed from `dob` + `country` at read time; the raw date of birth is
  redacted from partner reads. A member with unknown age is treated as a
  minor.

## Wallets

Every user gets an EVM wallet, provisioned automatically in the background
when they're created (`wallet.status` moves from `provisioning` to `active`).
It's global to the user - one wallet across all their memberships - and it's
where XP settles on-chain. You never manage keys; wallets are platform-custodied.

## Attributes: your org's custom fields

Beyond the fixed core profile, each organization enables its own typed
**attribute registry** - `text`, `number`, `date`, `boolean`,
`single_choice`, `multi_choice` - and writes per-member values against it
(`PUT /v1/users/{userId}/attributes`). Choice-typed attributes validate
against your configured choice list. Every value carries provenance, so you
can always tell whether a value came from the API, an admin, the member, or a
bulk import.

## Labels: lightweight admin grouping

**Labels** are free-form strings admins put on members ("u18-squad",
"season-ticket") - normalized (trimmed, lowercased), capped at 100 per
member. They're deliberately not entities: no schema to manage, just
consistent strings to filter and segment by in the console.

## Where to go next

* [Create a user](/walkthroughs/create-a-user) - the create/attach lifecycle
  in practice.
* [Migrate an existing member base](/walkthroughs/migrate-existing-members) -
  the same create-or-attach semantics, in bulk.
