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

# Register a new account

> Sente creates an account at a third-party app under the identity's email — driving signup, completing email verification from the identity's own inbox, and vaulting the credentials.

Register creates a **new** account at a third-party app under the identity's email address. Sente
drives a real browser through the signup form, completes email verification from the identity's own
inbox (OTP or magic link — the run controller reads the code and applies it, you never touch it),
and returns a durable account: credentials in an encrypted vault, session persisted, ready to
re-use.

For an account you already own, use [Connect](/guides/connect) instead — the two paths are
mutually exclusive per app (registering where a connection exists returns `409 ALREADY_CONNECTED`,
and vice versa).

<Warning>
  Register only at apps whose terms of service permit automated account creation, or use
  confirm-before-submit so a human performs the final submit and forms the agreement themselves.
  Some sites prohibit automated signup entirely — do not use Sente there. See
  [Acceptable use](/trust/acceptable-use).
</Warning>

## Start a registration

<CodeGroup>
  ```bash CLI theme={null}
  sente register https://app.example.com --identity <id>
  # run interactively and the CLI asks which submit mode you want; or be explicit:
  #   --confirm-before-submit   a human clicks the final submit
  #   --autonomous              fill and submit without pausing
  ```

  ```ts TypeScript theme={null}
  const { registration, run } = await sente.registrations.register({
    identityId,
    appUrl: "https://app.example.com",
  });
  const done = await sente.runs.waitForRun(run.id);
  if (done.status === "completed") {
    const creds = await sente.registrations.getCredentials(registration.id);
    // { username, password, origin }
  }
  ```

  ```python Python theme={null}
  res = sente.registrations.register(identity_id=identity_id, app_url="https://app.example.com")
  done = sente.runs.wait_for_run(res.run.id)
  if done.status == "completed":
      creds = sente.registrations.get_credentials(res.registration.id)
  ```
</CodeGroup>

You can pass a chosen `credentials: { username, password }`; omit them and Sente derives a username
and generates a password. Either way they end up in the vault, retrievable with
`getCredentials` (created accounts only — [connected](/guides/connect) accounts are write-only).

A run ends in one of three states — see [Runs and human takeover](/concepts/runs-and-human-takeover):

| Status      | Meaning                                                                                           |
| ----------- | ------------------------------------------------------------------------------------------------- |
| `completed` | The account exists and is verified. Credentials are vaulted.                                      |
| `blocked`   | A step needs a human. The run carries a `liveViewUrl`; a person clears the step, then you resume. |
| `failed`    | The attempt failed; `error.code` says why.                                                        |

Do **not** call `waitForOtp`/`waitForMagicLink` around a registration — verification is handled
inside the run. Those helpers are for signups your own code drives
([Receive verification codes](/guides/receive-verification-codes)).

## Confirm-before-submit

Pass `confirmBeforeSubmit: true` (CLI `--confirm-before-submit`) to keep a human in the loop for
the action that matters legally: pressing the final submit. The agent fills the whole form, then
stops. The run goes `blocked` with `error.code === "SUBMIT_CONFIRMATION_REQUIRED"` and a
`liveViewUrl`. A person opens the live view, reviews the form, clicks submit themselves — forming
the terms-of-service agreement — and you resume the run. Sente then finishes email verification as
usual.

<CodeGroup>
  ```bash CLI theme={null}
  sente register https://app.example.com --identity <id> --confirm-before-submit
  # → blocked (SUBMIT_CONFIRMATION_REQUIRED): open the printed liveViewUrl, click submit, then:
  sente run resume <runId>
  ```

  ```ts TypeScript theme={null}
  const { run } = await sente.registrations.register({
    identityId,
    appUrl: "https://app.example.com",
    confirmBeforeSubmit: true,
  });
  const done = await sente.runs.waitForRun(run.id);
  if (done.status === "blocked" && done.error?.code === "SUBMIT_CONFIRMATION_REQUIRED") {
    // a human clicks submit at done.liveViewUrl, then:
    await sente.runs.resume(run.id);
  }
  ```

  ```python Python theme={null}
  res = sente.registrations.register(
      identity_id=identity_id, app_url="https://app.example.com", confirm_before_submit=True
  )
  ```
</CodeGroup>

A blocked run holds for about 10 minutes before failing, so the human needs to be notified fast —
use the `run.blocked` [webhook](/guides/webhooks) or the `sente watch` desktop notifier.

## What blocks, what fails — honestly

Automated signup does not work everywhere, and Sente does not pretend otherwise:

* **CAPTCHAs block the run.** Sente does not complete CAPTCHAs. The run goes `blocked` with a
  live-view URL; a human completes the challenge in the interactive live view, then resumes.
* **Fraud and abuse walls exist.** Some apps silently reject or shadow-block signups they judge
  automated, sometimes before the verification email is ever sent. Those runs end `failed`. Sente
  cannot make a site accept a signup it has decided to refuse.
* **Phone verification is not supported.** A signup that requires SMS verification blocks for a
  human; Sente identities are email-only today.
* **Some sites prohibit automated account creation in their terms.** Do not register there — not
  even with confirm-before-submit if the terms ban automated form-filling too. Read the target's
  terms first. See [Acceptable use](/trust/acceptable-use).

Scope that works well: signups completable with email verification alone, at apps whose terms
permit it.

## After the run completes

* `sente credentials <registrationId>` / `getCredentials(id)` — the vaulted
  `{ username, password, origin }`.
* `sente relogin <registrationId>` / `registrations.login(id)` — re-authenticate later; returns a
  fresh `{ registration, run }`.
* The app's ongoing email (receipts, notifications, password-reset mail) keeps landing in the
  identity's inbox — read it like any other [message](/api-reference/messages).
* Open a logged-in browser or export the session — see [Sessions](/guides/sessions).

Registrations are subject to a per-org daily run cap (`429 RUN_LIMIT_EXCEEDED`) — see
[Limits](/trust/limits).
