# Users and profiles

> The user record, sign-up fields, custom profile fields and claims, name, password and username rules, verification and the account page.

Source: https://9in.io/docs/users/

## The user record

| Field | Notes |
|---|---|
| `id` | `usr_…`, or the id kept from an [import](https://9in.io/docs/importing-users/). The `sub` claim. Never changes. |
| `email`, `email_verified` | Lower-cased. Unique in the environment. |
| `phone_number`, `phone_number_verified` | E.164 (`+447700900123`). Unique. |
| `username` (also `preferred_username`) | Lower-cased. Unique. |
| `name`, `given_name`, `middle_name`, `family_name`, `nickname` | |
| `picture`, `website`, `gender`, `birthdate` (`YYYY-MM-DD`), `locale`, `zoneinfo` | Standard OpenID Connect profile claims |
| `metadata` | Your own JSON data. Not shown to the user, not in tokens (except custom fields, below). |
| `blocked` | A blocked user can't sign in; their sessions end and their tokens stop working. |
| `createdAt`, `updatedAt`, `lastLoginAt`, `loginCount` | Times in milliseconds |

A user needs at least one identifier: email, phone or username. Besides the record, a user has **identities** (password, `social:google`, `enterprise:bigcorp`…), **sessions**, and possibly **two-factor**.

Read and change users in the console (**Users**) or with the [Management API](https://9in.io/docs/reference/management-api/). When you create or update a user through the API, three names differ from what you get back: send `emailVerified`, `phone` and `phoneVerified`.

## Sign-up fields

**Login & Sign-Up → Sign-Up** chooses what the sign-up form asks for besides the identifier and password: name, given and family name, middle name, nickname, username, phone number, birthdate, gender, website, locale and time zone, each optional or required.

## Custom profile fields

**Login & Sign-Up → Custom Fields** adds your own fields: company, role, a marketing opt-in, a plan…

| Setting | Options |
|---|---|
| Key | `company` (lowercase letters, digits, `_`; standard claim names are reserved) |
| Type | Text, Number, Checkbox, Date, Dropdown (with options) |
| At sign-up | Hidden, Optional, Required |
| On the account page | Hidden, Read-only, Editable |
| Include as a claim | In ID tokens and `/oauth/userinfo`, with the `profile` scope |

Values are stored in the user's metadata under `fields`, so the Management API reads and writes them there:

```json
{ "metadata": { "fields": { "company": "Acme", "newsletter": true } } }
```

`PATCH /api/v1/users/{id}` replaces `metadata` as a whole: read the user first and send the merged object.

## Name, password and username rules

**Login & Sign-Up → Name, Password & Username Rules**:

- **Names:** which languages names may be written in (for example English, Swedish and Persian allow Latin letters with accents and the Arabic script), minimum and maximum length, digits, symbols and emoji. Invisible and text-direction characters are never allowed, so names can't impersonate others. Rules apply when people type their name (sign-up and the account page); names from social and enterprise sign-in, imports and the API are kept as they are.
- **Passwords:** minimum and maximum length and required character kinds. Checked when a password is chosen.
- **Usernames:** length, whether dots, underscores and hyphens are allowed, and whether it must start with a letter.

## Verified emails and phone numbers

An email or phone number becomes **verified** when the user proves they receive it: by signing in or resetting their password with a one-time code sent there, or by signing in with a provider that vouches for it ([social login](https://9in.io/docs/social-login/#linking-accounts), [enterprise SSO](https://9in.io/docs/enterprise-sso/)). Admins, imports and the API can set the flags directly. Verified emails are what accounts are linked by.

## The account page

Every tenant has an account page at `<issuer>/account`, themed like the sign-in pages, where signed-in users:

- edit their profile (the fields you choose in **Login & Sign-Up → Account Page**) and custom fields;
- change their password;
- turn two-factor on or off and get new recovery codes;
- see their sessions and end them, or sign out everywhere.

Link to it from your app, or point the user menu to your own profile page instead (**Login & Sign-Up → Account Page → Send users to your own account page instead**).

## Blocking and deleting

- **Block** (console, or `PATCH … { "blocked": true }`): the user can't sign in; their sessions end, refresh tokens stop working, and introspection reports their tokens inactive. Unblock to let them back in.
- **Delete** (console, or `DELETE /api/v1/users/{id}`): removes the user, identities, sessions and tokens for good. A `user.deleted` webhook goes out.
