User

Users: the people and companies your product acts for, each known by your own id.

class User

One of your users (a person or a company), keyed by your own id for it. User.fromId("user_42", { createIfMissing: true }) is lazy: nothing is sent until the user is used.

Attributes
idstring

Your id for the user.

namestring | null
emailstring | null
phonestring | null
phoneVerifiedAtDate | null

When the phone was proven (null if never).

spendCapUsdPerMonthnumber | null
metadataJsonObject | null
timezonestring | null

Their IANA timezone (null: UTC).

statusstring
createdAtDate | null
spendingSpending | null

Whether they can spend right now: paused or not, what NoClick tells them, and how many of their messages wait (see pauseSpending).

consoleUrlstring | null

This user in the developer console (null off the hosted API).

humanHuman

The person behind this user: await (await user.human.approve("Send it?")).wait().

createstatic

static create(
  id: string,
  options?: UserFields & { idempotencyKey?: string; client?: NoClick },
): Promise<User>

Create a user with your id for it. A taken id throws Conflict (its existingId is that id).

Parameters
idstringrequired
options.namestring | null
options.emailstring | null
options.phonestring | null
options.spendCapUsdPerMonthnumber | null
options.metadataJsonObject | null
options.timezonestring | null

Where they are, as an IANA name ("America/New_York"): every turn of an agent acting for them starts with the date and time there (unless the agent has its own timezone), and Cron with tz: "user" fires in it, following them when they move.

options.idempotencyKeystring

Makes a retried create safe: the same key returns the first result. Generated when omitted.

options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

The new user, loaded.

fromIdstatic

static fromId(
  id: string,
  options?: UserFields & { createIfMissing?: boolean; client?: NoClick },
): User

A lazy reference by your id. With createIfMissing your code is the definition: it's created with the fields on first use, and an existing user whose fields differ is updated to match (a field left out is never changed; null clears one, as in update).

Parameters
idstringrequired
options.createIfMissingboolean
options.namestring | nullomit to leave it unchanged
options.emailstring | nullomit to leave it unchanged
options.phonestring | nullomit to leave it unchanged
options.spendCapUsdPerMonthnumber | nullomit to leave it unchanged
options.metadataJsonObject | nullomit to leave it unchanged
options.timezonestring | null

Where they are, as an IANA name ("America/New_York"): every turn of an agent acting for them starts with the date and time there (unless the agent has its own timezone), and Cron with tz: "user" fires in it, following them when they move.

(omit to leave it unchanged)
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

A user that loads, or is created, the first time it's used. Nothing is sent yet.

getstatic

static get(id: string, options?: { client?: NoClick }): Promise<User>

Load a user by your id now; an unknown id raises noclick.NotFound.

Parameters
idstringrequired
options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

The user, loaded.

liststatic

static list(options?: UserListOptions & { limit?: number }): Promise<User[]>

Your users, newest first (or the first limit).

Parameters
options.qstring

A case-insensitive prefix of the id, name or email.

options.status"active" | "suspended"
options.spending"paused" | "active"

Only users whose spending is (or isn't) paused.

options.limitnumber

Return at most this many.

options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

Every matching user, fetched page by page.

listPagestatic

static listPage(options?: UserListOptions & PageOptions): Promise<Page<User>>

One page of users; pass nextCursor back as cursor.

Parameters
options.cursorstring | null

The next_cursor of the page before; omit it for the first page.

options.limitnumber

Return at most this many.

options.qstring

A case-insensitive prefix of the id, name or email.

options.status"active" | "suspended"
options.spending"paused" | "active"

Only users whose spending is (or isn't) paused.

options.clientNoClick

The client to send with; defaults to the module client built from NOCLICK_API_KEY.

Returns

A page whose data holds the users and whose next_cursor is None on the last page.

update

update(changes: UserFields & { id?: string }): Promise<this>

Change fields (null clears one, omitted ones stay). A new id renames the user: everything it owns follows, and a taken id throws Conflict. A user acting for themselves may change their own timezone, their session included.

Parameters
changesUserFields & { id?: string }required
Returns

This user, updated.

suspend

suspend(): Promise<this>

Stop all activity for this user.

Returns

This user, now suspended.

pauseSpending

pauseSpending(
  options?: { message?: string; action?: SpendingAction },
): Promise<this>

Stop everything that costs money for this user until resumeSpending(), and say what they can do about it. Call it from your billing when they run out (say, at a balance alert) or fall behind. message is what NoClick tells them, in your words, up to 500 characters; action is your checkout or billing page. Both may use {{user.id}}, {{user.name}}, {{user.email}} and {{user.metadata.<key>}}, filled in now (a field this user lacks throws InvalidRequest). Without message, the default you set in the console is used; with no default either it throws InvalidRequest. Without action, the default's button.

While paused, a call your code makes for them throws SpendingPaused; a message they send an agent is answered once per conversation with message and action and held, up to 24 hours, to run when you resume; a call to a number they reach hears message; schedules, webhooks and app events for their agents are skipped. Work under way finishes the step it's on, and what they already have keeps running and billing. Only a key acting for your whole account can pause or resume.

await user.pauseSpending({ message: "You've used your credits.", action: { label: "Top up", url: topUpUrl } });
Parameters
options.messagestring
options.actionSpendingAction
Returns

This user, with spending paused.

resumeSpending

resumeSpending(): Promise<this>

Let this user spend again. What was held for them runs now, in the order it arrived, each with when it arrived so the agent knows it waited. Resuming a user who isn't paused changes nothing.

Returns

This user, with spending no longer paused.

delete

delete(): Promise<void>

Mark the user deleted, which frees its id. Invite-only beta: nothing acts for them afterwards (their connections' grants are revoked at each provider, their agents' triggers stop, their inboxes stop receiving mail and their numbers are released), while the record (operations, tool calls, conversations, usage and spend) and the data their resources hold stay until you delete them. { export: true } packs up everything the user holds first, as export() does, and deletes the user once the export is stored; wait() resolves to the ExportBundle. Nothing is deleted if the export fails or is canceled. Only a call acting for the account deletes users.

Returns

None; with export=True, an operation whose .wait() gives the ExportBundle once the user is deleted.

export

export(): Promise<Operation<ExportBundle>>

Pack up everything the user holds, in forms that work without NoClick: their own agents' definitions as JSON, their conversations with any agent as JSON Lines transcripts, what agents remember about them as Markdown, their databases as SQL, their buckets' and volumes' files, their dicts and queues as JSON Lines, their repos as git bundles, their apps' settings, connections and secrets by name only (never a token or a value), and each phone number and domain with the call that moves it (transferOut). The user keeps working; one export of a user runs at a time (another throws Conflict naming it). wait() resolves to the ExportBundle: a zip url valid until expiresAt (7 days), its contents, and remainingDependencies.

Returns

An operation whose .wait() gives the ExportBundle: a zip url valid until expires_at (7 days), its contents, and remaining_dependencies, what still runs on NoClick.

verifyPhone

verifyPhone(options?: { phone?: string }): Promise<PhoneVerification>

Text a verification code to the user's phone (or phone, which becomes its number); confirm it with checkPhone(code). Resolves to the number the code went to, and when the code expires.

Parameters
options.phonestring
Returns

The number the code went to, and when the code expires.

checkPhone

checkPhone(code: string): Promise<JsonObject>

Check the code the user received; on success the phone is verified. A wrong code throws InvalidRequest, an expired one Expired, and too many tries RateLimited.

Parameters
codestringrequired
Returns

True once the phone is verified; phone_verified_at is then set.

session

session(options: { scopes: string | string[]; ttlS?: number }): Promise<Session>

Mint a short-lived token that acts only as this user, with scopes (a subset of your key's: agents, humans, credentials:request, credentials:use, channels, inbox, ai); ttlS is at most 24h. Hand session.token to your frontend, or use NoClick.forSession(session). Revoking the minting key revokes its sessions.

Parameters
options.ttlSnumber
options.scopesstring | string[]required
Returns

The session: its token, the scopes it carries and when it expires.

PhoneVerification

interface PhoneVerification

A verification code on its way to the user's phone.

Attributes
phonestring | null
statusstring | null
expiresAtDate | null
rawJsonObject

The response JSON exactly as the API sent it.

Spending

interface Spending

Whether a user can spend right now (user.spending). A paused user can't start anything that costs money until resumeSpending(); message and action are what NoClick tells them meanwhile, since is when you paused them, held how many of their messages wait to run when you resume, and pausedBy the key that paused them ("console" from the console).

Attributes
pausedboolean
messagestring | null
actionSpendingAction | null
sinceDate | null
heldnumber
pausedBystring | null
rawJsonObject

The response JSON exactly as the API sent it.