https://api.sente.run/v1.
1
Get an API key
Sign in at app.sente.run. The first sign-in creates your organization
and puts you on the free tier — no card.On the API keys page, create a key and export it:The API accepts it as
Authorization: Bearer <key>. One key authenticates the whole
organization — treat it like a production secret.2
Install a client
sente login opens a browser and mints a key for you, so you can skip step 1. In CI, set
SENTE_API_TOKEN instead — it always wins over the stored file.3
Connect an account you already own
You supply the username and password once. Sente logs in with a real browser, vaults the
credentials write-only, and keeps the account re-loginable. No
identityId —
the backing email address is provisioned from the app’s hostname.Registering a new account is the same shape —
sente register <appUrl> /
registrations.register({ appUrl }) — and is only for apps whose terms permit it. Add
--confirm-before-submit / confirmBeforeSubmit: true so a human clicks the final submit and
accepts the app’s terms. See Register.4
Wait for the run, and handle a block
Connecting starts a run: one browser job. It ends Email verification is the one step you never handle: every inbound email to the account’s
address is classified on arrival, and the run injects the code or link itself. See
Verification codes.
completed or failed, or stops at
blocked — meaning a human step is required. Nothing is worked around; the run holds for
10 minutes with an interactive live view, then fails with BLOCKED_TIMEOUT.5
Use the logged-in session
getSession hands back a remote browser already signed in, as a CDP URL. If the login went
stale, Sente re-logs in first (vaulted credentials plus a fresh code from the account’s inbox)
and sets healed: true — a cold call can take a minute.One live session per identity, and open sessions bill per minute — always close them. To use
your own browser stack instead, export a portable Playwright
storageState:
sente session export <registrationId> / registrations.exportSession(id). See
Sessions.What just happened
You never created an email identity, but one exists. WhenidentityId is omitted, Sente
auto-provisions the backing identity from the app’s hostname: app.example.com becomes
app-example@sente.run, and a taken address gets a short random suffix
(app-example-x7k2@sente.run). That address is a real mailbox — it receives the app’s
verification emails, notifications, and password resets, and the run reads them.
- The identity counts against your plan’s identity cap. If auto-provisioning would exceed it, the
call returns
429 IDENTITY_LIMIT_EXCEEDED— pass an existingidentityIdto reuse an address across several apps, or upgrade. - If the connect or register itself then fails, the auto-created identity is rolled back, so a failed attempt does not eat the cap.
identityId explicitly when you want several accounts to share one mailbox, or when the
address matters (it appears in the app’s UI as the account’s email).
When it doesn’t work
Full lists: Run statuses and error codes · Human takeover.
Let a coding agent do the setup for you
Let a coding agent do the setup for you
Paste this into Claude Code, Cursor, or any coding agent that can read a URL:The agent installs the CLI, runs
sente login, provisions an identity, writes the key to .env,
and wires send/receive into your codebase. One step still needs you: sente login opens a browser
for you to sign in.Next steps
- Accounts — the account object,
createdvsconnected, and how the identity relates to it. - Verification codes —
waitForOtpandsente wait --otpfor the signups you drive yourself. - Webhooks — get pushed
run.blocked,run.completed, andrun.failedinstead of polling.
