Bucket
Buckets: files by key, private by default, with signed links and an S3-compatible escape hatch.
bucket = noclick.Bucket.from_name("uploads", create_if_missing=True)
bucket.put("invoices/0042.pdf", pdf_bytes, content_type="application/pdf")
link = bucket.signed_url("invoices/0042.pdf", expires_in=3600)A key is a path-like name (invoices/0042.pdf); / separates folders only
by convention, so listing with delimiter="/" shows them as folders.
class BucketA bucket of files by key. Private by default: files are reached through this client or a
signedUrl; a public bucket also serves each file at url(key). Its region is a location hint
object storage places it by when it has room there, fixed when it's created.
- Like every live object, it also has hydrate(), refresh() and raw.
| id | string | |
| name | string | |
| public | boolean | Whether every file is readable at |
| sizeBytes | number | null | |
| objectCount | number | null | |
| publicBaseUrl | string | null | Where a public bucket serves its files (null while it's private). |
| usedBy | UsedBy[] | Who uses it: apps that bind it and agents with it in their tools. |
| notifications | BucketNotification[] | Where it tells about new files ( |
| region | RegionName | null | The region it keeps its data in, fixed when it was created. |
| userId | string | null | |
| createdAt | Date | null | |
| consoleUrl | string | null | This bucket in the developer console (null off the hosted API). |
only
only(...operations: BucketTool[]): BucketOperationsA tool ref to some of its operations, for tools: "objects", "head", "put" (store a
file from a url or from text, so the model never handles bytes), "signed_url" (a link
that reads a file) and "remove". The bucket itself in tools gives all five, as
{name}__objects and so on; policy names them bucket.objects, bucket.put, ... (bucket.*).
A ref to just those operations, to list in tools=; bind(...) fixes arguments.
createstatic
static create(name: string, options?: BucketCreateOptions): Promise<Bucket>Create a bucket, unique by name per user (a taken name throws Conflict with existingId).
Serve every file at a plain URL (url(key)); private by default.
false)Where it runs or keeps its data (regions()); omitted, your account's default region.
undefined = the ambient user (asUser), null = the account itself.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
The new, empty bucket.
fromNamestatic
static fromName(
name: string,
options?: BucketCreateOptions & { createIfMissing?: boolean },
): BucketA lazy reference to the bucket called name for the current (or given) user. With
createIfMissing it's created on first use; one that exists is used as it is.
Serve every file at a plain URL (url(key)); private by default.
false)Where it runs or keeps its data (regions()); omitted, your account's default region.
undefined = the ambient user (asUser), null = the account itself.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
A bucket that loads (or is created) the first time it's used. Nothing is sent yet.
fromIdstatic
static fromId(bucketId: string, options?: CallOptions): BucketA lazy reference to a bucket by id.
A bucket that loads the first time you read a field. Nothing is sent yet.
getstatic
static get(bucketId: string, options?: CallOptions): Promise<Bucket>Load a bucket by id now; an unknown id raises noclick.NotFound.
The bucket, loaded: whether it's public, how many files it holds and their total size.
liststatic
static list(options?: ReadOptions & { limit?: number }): Promise<Bucket[]>The current user's buckets (or those userFilter covers).
Return at most this many.
Which users the read covers (user_id query), instead of acting as one (user).
undefined = the ambient user (asUser), null = the account itself.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
Every matching bucket, newest first, fetched page by page.
listPagestatic
static listPage(options?: ReadOptions & PageOptions): Promise<Page<Bucket>>One page of buckets; pass nextCursor back as cursor.
The next_cursor of the page before; omit it for the first page.
Return at most this many.
Which users the read covers (user_id query), instead of acting as one (user).
undefined = the ambient user (asUser), null = the account itself.
The client to send with; defaults to the module client built from NOCLICK_API_KEY.
A page whose data holds the buckets and whose next_cursor is None on the last page.
put
put(
key: string,
data: BucketData,
options?: BucketPutOptions,
): Promise<BucketObject>Store data at key, replacing what was there (up to 100 MB; larger files go through a PUT signed link).
Guessed from the key's extension when omitted.
Up to 2 KB of your own string pairs, returned with the file.
The file as stored, with its size and etag.
read
read(key: string): Promise<Uint8Array>The file's bytes; a missing key throws NotFound.
The file's bytes, exactly as stored; decode text yourself.
head
head(key: string): Promise<BucketObject>A file's size, type, etag and metadata, without downloading it.
The file's size, content type, etag, metadata and when it last changed.
objects
objects(
options?: BucketObjectsOptions & { limit?: number },
): Promise<BucketObject[]>The files under prefix, in key order (or the first limit), fetched page by page.
"/" rolls keys below the next / into one folder entry each.
Return at most this many.
Every matching file (or the first limit), fetched page by page.
objectsPage
objectsPage(
options?: BucketObjectsOptions & PageOptions,
): Promise<Page<BucketObject>>One page of objects; pass nextCursor back as cursor.
"/" rolls keys below the next / into one folder entry each.
The next_cursor of the page before; omit it for the first page.
Return at most this many.
A page whose data holds BucketObjects and whose next_cursor is None on the last page.
remove
remove(key: string): Promise<void>Delete the file at key (a key that isn't there is fine).
versions
versions(key: string): Promise<ObjectVersion[]>What key held before each write through NoClick of the last 30 days, newest first.
Each earlier version.
restoreVersion
restoreVersion(
key: string,
version: ObjectVersion | string,
): Promise<BucketObject>Put key back as version held it; what it holds now is kept as a version in turn.
The file, as it's stored again.
signedUrl
signedUrl(key: string, options?: BucketSignedUrlOptions): Promise<string>A link that reads (GET) or uploads (PUT) the file without a NoClick key, until it expires.
GET reads the file, PUT uploads it (up to 5 GB).
"GET")Seconds the link works: 60 to 604,800 (a week); 3600 by default.
3600)A PUT link's upload must send this type.
The link. Anyone who has it can use it until it expires, so hand it only to whoever needs it.
url
url(key: string): Promise<string>The plain URL a public bucket serves key at; a private bucket throws NotAvailable.
public_base_url followed by the key; it works for as long as the bucket stays public.
update
update(options: { public?: boolean }): Promise<this>Change the bucket's settings; making it private stops every public URL at once.
This bucket, with the server's current fields.
notifyinvite-only beta
notify(
queue: string | { _ensure(): Promise<JsonObject> },
options?: { prefix?: string; enabled?: boolean },
): Promise<this>Invite-only beta.
Put a message on queue (a Queue or its name, in the bucket's own user) for every file stored
under prefix (the whole bucket when omitted), however it arrived: put, a PUT signed link or
S3 credentials. The message is { event: "put", bucket, key, size, content_type, etag, at }.
Asking again for the same queue and prefix changes nothing; enabled: false stops it.
await recordings.notify("new-recordings", { prefix: "calls/" });This bucket, whose notifications list where it tells.
s3Credentialsinvite-only beta
s3Credentials(
options?: { readOnly?: boolean; ttlS?: number },
): Promise<S3Credentials>Invite-only beta. Keys for the S3-compatible endpoint, valid ttlS seconds (900 to 43,200; 3600 by default).
3600The endpoint, bucket name, keys and expires_at. The secret is shown once; mint new ones when they expire.
export
export(): Promise<Operation<ExportBundle>>Export every file, to take anywhere: a zip holding each one at its key (under
buckets/<name>/files/), with index.jsonl listing each key's content type and metadata. A
key that can't be a path in a zip (an empty, . or .. part) is kept under renamed/, and the
index says which. wait() resolves to an ExportBundle: the zip at url, valid 7 days.
An operation whose wait() gives an ExportBundle: the zip at url, valid 7 days.
delete
delete(options?: { force?: boolean }): Promise<TrashItem>Delete the bucket: it goes to the trash, restorable for 30 days (its files stored, and billed,
until it's purged). It must be empty unless force (which takes its files too), and in no
agent's tools. Returns its TrashItem.
Its TrashItem: restore() puts it back, files and all.
BucketObject
interface BucketObjectA file in a bucket. In a listing with a delimiter, an entry with isFolder stands for
every key under that prefix, and only its key is set.
| key | string | |
| size | number | null | |
| contentType | string | null | |
| etag | string | null | Changes whenever the content does. |
| metadata | Record<string, string> | |
| updatedAt | Date | null | |
| isFolder | boolean | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
ObjectVersion
interface ObjectVersionWhat a file held before a write through NoClick replaced it (op changed) or removed it
(deleted), kept 30 days. An upload through a signed link or S3 credentials keeps none.
| id | string | |
| key | string | |
| op | "changed" | "deleted" | |
| size | number | null | |
| replacedAt | Date | null | |
| raw | JsonObject | The response JSON exactly as the API sent it. |
BucketOperations
class BucketOperationsSome of a bucket's operations as an agent's tools (bucket.only(...)), with the arguments bind(...) fixed.
| bucket | Bucket | |
| operations | BucketTool[] | |
| bindings | JsonObject | The arguments NoClick fills on every call, out of the model's reach. |
bind
bind(args: JsonObject): BucketOperationsFix arguments of these operations, as ConnectionOperations.bind does. prefix is the one to
bind here: every key the tools take and return is then under it, so one bucket holds a folder
per user.
uploads.only("objects", "put", "signed_url").bind({ prefix: "users/{{user.id}}/" })A new ref with these arguments bound on top of any bound before.
S3Credentialsinvite-only beta
interface S3CredentialsInvite-only beta.
Short-lived keys for the bucket's S3-compatible endpoint (rclone, the AWS CLI, an S3
library). bucket is its name on that endpoint, not its NoClick name.
| endpoint | string | |
| bucket | string | |
| accessKeyId | string | |
| secretAccessKey | string | |
| sessionToken | string | null | |
| region | string | |
| readOnly | boolean | |
| expiresAt | Date | null | |
| raw | JsonObject | The response JSON exactly as the API sent it. |