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

# Identities and registrations

> The two objects in Sente's data model — the identity (an email address and inbox) and the registration (an account at one app) — and why they are separate.

Sente's data model has two core objects. Keeping them straight makes the rest of the product predictable.

* An **identity** is the communication layer: one managed email address and its inbox.
* A **registration** is the identity's account at **one** third-party app.

One identity can hold many registrations. A registration always belongs to exactly one identity.

## Identity

An identity is a real email address on `sente.run` (for example `acme-bot@sente.run`) with a live inbox behind it. It is:

* **Owned by your org.** Created via the API, scoped to your API key.
* **Long-lived.** It is not a disposable inbox. The address keeps receiving mail for as long as it exists, so password resets, receipts, and notification emails from every app keep arriving.
* **Reused across apps.** The same identity can sign up to, or connect to, many apps.
* **Useful with zero registrations.** An identity is a working send/receive email address on its own. Many agents use one purely for email — including [waiting for verification codes](/guides/receive-verification-codes) during a signup the agent performs elsewhere.

Every inbound email to an identity is parsed and annotated server-side (`otp`, `magic_link`, or `other`), which is what makes `waitForOtp` / `waitForMagicLink` work. See [Receive verification codes](/guides/receive-verification-codes).

The identity is **not** the account-holder at any app. That is the registration's job.

<CodeGroup>
  ```bash CLI theme={null}
  sente identity create --name acme-bot --local-part acme-bot
  # → acme-bot@sente.run   (omit --local-part for a random address)
  ```

  ```ts TypeScript theme={null}
  const identity = await sente.identities.create({ name: "acme-bot", localPart: "acme-bot" });
  // identity.email → "acme-bot@sente.run"   (omit localPart for a random address)
  ```

  ```python Python theme={null}
  identity = client.identities.create(name="acme-bot", local_part="acme-bot")
  # identity.email → "acme-bot@sente.run"   (omit local_part for a random address)
  ```
</CodeGroup>

## Registration

A registration is the identity's account at one app: `https://app.example.com` plus a username, credentials, and a logged-in browser session. There are two kinds:

| `kind`      | How it got here                                                                                     | Credentials                                                              |
| ----------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| `created`   | Sente registered a new account at the app under the identity's email ([Register](/guides/register)) | Readable and writable via the API                                        |
| `connected` | You already own the account and supplied its credentials ([Connect](/guides/connect))               | **Write-only** — `GET /credentials` returns `403 CREDENTIALS_WRITE_ONLY` |

What lives **on the registration**, not on the identity:

* **Credentials** — username/password, encrypted at rest in the vault.
* **The logged-in session** — re-login and [CDP/`storageState` handoff](/guides/sessions) are addressed by registration ID.
* **The TOTP seed** (connected accounts, optional) — used server-side to compute the 30-second authenticator code at login. The seed never reaches any model and can never be read back.
* **Status** — `pending`, `active`, `failed`, or `disabled` (a revoked connection).

A registration is created or refreshed by a [run](/concepts/runs-and-human-takeover) — one browser job that performs the signup or login.

<Note>
  Connected accounts require a username/password login form at the app. Accounts that only sign in through SSO (Google, Okta) or passkeys cannot be connected.
</Note>

## Why the split matters

**Verification email routes itself.** Every app a registration exists at sends its mail — signup OTPs, magic links, password resets, notifications — to the identity's one address. Sente completes email verification from the identity's own inbox during runs, and your agent can read the same inbox at any time. No per-app inbox plumbing.

**One address, many accounts.** The identity is the stable thing you configure once (webhooks, allowlists, the address you tell people). Registrations come and go underneath it without touching that surface.

**Credentials are scoped to one app.** Revoking one connection (`connections.revoke`) or deleting it (revoke plus purge of the vaulted credentials and seed) affects only that registration. The identity and its other registrations are untouched.

**Different trust levels per kind.** A `connected` registration is owner-authorized: you supplied the credentials, they are write-only afterward, and you can revoke at any time. A `created` registration is an account Sente made — with its own credentials in the vault, readable by you. The API keeps the two from colliding: registering where a connection exists (or vice versa) returns `409`.

**Runs and sessions serialize per identity.** One run at a time per identity, and one live browser session per identity. Splitting agents across identities is how you get parallelism.

## Where to go next

<CardGroup cols={2}>
  <Card title="Runs and human takeover" href="/concepts/runs-and-human-takeover">
    What a run is, its lifecycle, and what happens when it needs a human.
  </Card>

  <Card title="API reference: identities" href="/api-reference/identities">
    Create, list, and get identities.
  </Card>

  <Card title="API reference: registrations" href="/api-reference/registrations">
    The full registration surface, including credentials and sessions.
  </Card>

  <Card title="API reference: connections" href="/api-reference/connections">
    Connect, revoke, and delete owner-authorized accounts.
  </Card>
</CardGroup>
