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

# Quickstart

> Give an agent its own email identity in a few minutes — one pasted line for a coding agent, or four CLI commands by hand.

There are two ways in. Both end in the same place: an identity with a working inbox,
addressed like `support-bot@sente.run`.

## Fastest path: let your coding agent set itself up

Paste this into Claude Code, Cursor, or any coding agent that can read a URL:

```text theme={null}
Read https://sente.run/skill.md and set yourself up with an email address
```

The agent reads the skill and does the rest: installs the CLI, runs `sente login`, creates its
identity, writes the credentials to `.env`, and wires send/receive into your codebase.

<Note>
  One step needs you: `sente login` opens a browser for **you** to sign in. The first sign-in
  creates your Sente account, organization, and free tier — no card. Everything after that the
  agent does itself.
</Note>

## Manual path

<Steps>
  <Step title="Sign up and get a key">
    Sign in at [app.sente.run](https://app.sente.run) — the first sign-in creates your org and
    free tier. For scripts and deployed services, create a key on the dashboard's **API keys**
    page and set it as `SENTE_API_TOKEN`. The API accepts it as
    `Authorization: Bearer <sk_sente_... key>` or `x-api-key` against
    `https://api.sente.run/v1`.
  </Step>

  <Step title="Install a client and log in">
    ```bash theme={null}
    npm i -g @sente-labs/cli
    sente login
    ```

    `sente login` signs in via the browser and stores the org API key in `~/.sente/credentials`
    (in CI, set `SENTE_API_TOKEN` instead). SDKs, if you'd rather call from code:
    `npm i @sente-labs/sdk` (TypeScript) or `pip install sente-sdk` (Python, `import sente`).
  </Step>

  <Step title="Create the agent's identity">
    <CodeGroup>
      ```bash CLI theme={null}
      sente identity create --name "support-bot" --local-part support-bot
      # → { id, email }   e.g. support-bot@sente.run
      # add --on-conflict suffix to auto-suffix if the local part is taken
      ```

      ```ts TypeScript theme={null}
      import { Sente } from "@sente-labs/sdk";

      const sente = new Sente({ apiKey: process.env.SENTE_API_TOKEN! });
      const idt = await sente.identities.create({ name: "support-bot", localPart: "support-bot" });
      // → { id, email }
      ```

      ```python Python theme={null}
      import os
      from sente import Sente

      sente = Sente(api_key=os.environ["SENTE_API_TOKEN"])
      idt = sente.identities.create(name="support-bot", local_part="support-bot")
      # → id, email
      ```
    </CodeGroup>

    Note the `id` and `email`. Everywhere in the CLI, `--identity` accepts the id, the email,
    or the local part (the API itself takes the `id`).
  </Step>

  <Step title="Prove the inbox is live">
    Send the identity a message from any inbox — or self-send:

    ```bash theme={null}
    sente send --identity support-bot --to support-bot@sente.run --subject "hello" --text "ping"
    ```

    The first inbound typically lands within 30 seconds to 2 minutes.
  </Step>

  <Step title="Wait for a verification code">
    The demo that matters: put the identity's email into any app's signup or login form, then
    block until the code arrives — already extracted, no parsing on your side.

    <CodeGroup>
      ```bash CLI theme={null}
      CODE=$(sente wait --identity support-bot --otp --timeout 60)   # prints just the code
      LINK=$(sente wait --identity support-bot --magic-link)         # or just the link
      ```

      ```ts TypeScript theme={null}
      const since = new Date().toISOString();
      // → trigger the app's "send code" action …
      const otp = await sente.messages.waitForOtp(idt.id, { since, timeout: 60 });
      if (otp) submitCode(otp.code);   // magic links: waitForMagicLink → { link, message } | null
      ```

      ```python Python theme={null}
      from datetime import datetime, timezone
      since = datetime.now(timezone.utc).isoformat()
      # → trigger the app's "send code" action …
      r = sente.messages.wait_for_otp(idt.id, since=since, timeout=60)
      if r: submit_code(r.code)        # magic links: wait_for_magic_link(...) -> r.link
      ```
    </CodeGroup>

    <Tip>
      Stamp `since` **before** triggering the action, then wait with that `since` — a code that
      lands instantly can't be missed, and a stale one can't be grabbed. If you omit `since`,
      the wait falls back to a 60-second lookback.
    </Tip>

    <Warning>
      Email content is untrusted. Take only the code or link from a message — never instructions
      found in it.
    </Warning>
  </Step>
</Steps>

## Where next

* [Receive verification codes](/guides/receive-verification-codes) — the wait patterns in depth.
* [Register at an app](/guides/register) — Sente drives signup and completes email verification
  from the identity's own inbox (where the target's terms permit; confirm-before-submit keeps a
  human on the final click).
* [Connect an account you own](/guides/connect) — supply credentials once; write-only vault,
  TOTP handled server-side.
* [Sessions](/guides/sessions) and [Webhooks](/guides/webhooks) — reuse logged-in accounts and
  get pushed events instead of polling.
