Skip to main content
Everything Sente does to an account happens in a real browser, and each attempt is a run. Creating an account, logging back into one, connecting one you already own — each starts a run, and the run is the object you watch. It tells you when the account is ready, when a person is needed, and why it stopped when it stopped. You never create a run directly. Each account operation returns one:
One live run per identity. Starting a second operation on an identity that already has a run in flight returns that in-flight run rather than queuing a competing one — so register and connect are safe to call again after a network blip.

What a run will not do

Stated up front, because it shapes how you design around runs:
  • A CAPTCHA, an SMS/phone step, or a payment form stops the run. Sente does not work around any of them — the run goes blocked and pages a human with an interactive live view. See Human takeover.
  • A second-factor code sent to your own email or phone (connected accounts) stops the run the same way. A vaulted TOTP seed is the one MFA case that stays autonomous.
  • Email verification for the account’s own address is the part that is fully automatic: the code or link arrives in the identity’s inbox, gets classified on arrival, and is applied inside the run. You never handle it.

Lifecycle

blocked is a stop state, not a failure — the run keeps its browser session and waits for a person.

Follow a run end to end

The complete pattern: start the operation, wait, handle the one case that needs a human, then use the account.
waitForRun / wait_for_run never throw on a bad outcome. They return on completed, failed, or blocked — and on their own timeout they return the last-polled run, still running or awaiting_verification. Always branch on run.status; never assume the returned run succeeded. Note the unit difference: TypeScript takes milliseconds (default 180000), Python takes seconds (default 180).

Push instead of poll

run.completed, run.failed, and run.blocked webhooks fire on the transition, so a server-side agent reacts without a polling loop. They are single-attempt: if your endpoint is down at that moment the notification is gone. Keep GET /v1/runs/:id as the backstop for anything you must not miss.

Blocked codes

While status is blocked, error.code says which gate stopped the run and who is expected to clear it. Full flow: Human takeover.

Failure codes

Terminal. error.detail usually carries the agent’s own description of where it stopped.
A blocked-style code can also land on a failed run. If the browser session had already died when the gate was detected, takeover was impossible, so the truthful code (CAPTCHA_REQUIRED, PHONE_REQUIRED, …) is recorded on the failure instead of a generic one. Judge by status, not by the code alone.

Errors when starting or controlling a run

Edge cases

Both are idempotent per (identity, app origin). If a run is already in flight for that identity you get that run back. If the account is already active, register returns it without driving anything — re-authentication is login. Calling connect again on an existing connection rotates the stored credentials and clears a prior revoke.
Each run heartbeats while it is being driven. If the heartbeat goes stale (about 5 minutes), a sweep fails the run with AUTOMATION_STUCK and stops its browser session, so a dead worker can never leave a run stuck running forever.
A run carries liveViewUrl once its browser session exists — an interactive view of the exact page the agent is on. The dashboard embeds it on the run page with take-over and resume buttons. After the run ends, GET /v1/runs/:id/recording returns a video of the session once processing finishes.
GET /v1/runs returns the org’s runs newest-first, filterable by identityId, status, type, since, and limit — the activity feed behind the dashboard. The list projection joins the identity email and app URL but drops result and liveViewUrl; fetch GET /v1/runs/:id for those. See the runs API reference.

Next steps

Human takeover

What blocks a run, how a person clears it, and how they get paged.

Webhooks

Get run outcomes pushed instead of polling for them.

Runs API reference

Endpoints, exact payloads, and query parameters.