Keys
The keys resource manages API keys: minting new keys with a specific
permission scope, listing existing keys, fetching detail, and revoking
keys when they're no longer needed. Keys are how every other SDK call
authenticates against Buckt.
create
keys.createPOST/v1/keyskeys.create(opts: {
name: string;
permissions: Permission[];
expiresAt?: Date;
bucketIds?: string[];
}): Promise<ApiKeyCreateResponse>Mints a new API key. Pass an expiresAt Date to time-box keys handed
to short-lived environments (CI, contractor access, ephemeral previews).
Pass bucketIds to scope the key to a specific subset of buckets.
| Name | Type | Default | Description |
|---|---|---|---|
| namerequired | string | — | Display name for the key. Shown in the dashboard. 1–80 characters. |
| permissionsrequired | Permission[] | — | Scope set granted to the key. See [Authentication](/authentication#available-scopes) for the full list. |
| expiresAt | Date | — | When the key stops working. Serialized to ISO 8601 on the wire. Omit for keys that never expire. |
| bucketIds | string[] | — | Restrict the key to a specific subset of buckets. Calls against other buckets return 404. |
const key = await client.keys.create({
name: "CI uploader",
permissions: ["files:write"],
expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
bucketIds: ["bkt_01H8XYZABCDEFGHJKMNPQRSTVW"],
});
// Copy `key.key` now — the secret is never returned again.
console.log(key.key);{
"object": "api_key",
"id": "key_01H8XYZABCDEFGHJKMNPQRSTVW",
"key": "bkt_live_aBcD1234EfGh5678IjKl9012MnOp"
}list
keys.listGET/v1/keyskeys.list(opts?: {
cursor?: string;
limit?: number;
}): Promise<{ data: ApiKey[]; meta: CursorMeta }>Lists keys in the organization. The list endpoint never returns secrets
— only metadata. Use lastUsedAt to spot stale keys that are good
candidates for revocation.
| Name | Type | Default | Description |
|---|---|---|---|
| cursor | string | — | Opaque cursor returned from a previous call. Omit for the first page. |
| limit | number | 25 | Page size. Maximum 100. |
const { data, meta } = await client.keys.list({ limit: 50 });
for (const key of data) {
console.log(key.id, key.name, key.lastUsedAt);
}{
"data": [
{
"object": "api_key",
"id": "key_01H8XYZABCDEFGHJKMNPQRSTVW",
"name": "CI uploader",
"prefix": "bkt_live_aBcD",
"lastUsedAt": "2026-04-25T12:34:56Z",
"createdAt": "2026-03-01T08:00:00Z"
}
],
"meta": { "limit": 25, "nextCursor": null }
}get
keys.getGET/v1/keys/{id}keys.get(id: string): Promise<ApiKeyDetail>Fetches a single key's full detail — including permissions, scoped
buckets, and expiry. Throws NotFoundError if the id is unknown.
const key = await client.keys.get("key_01H8XYZABCDEFGHJKMNPQRSTVW");
console.log(key.permissions, key.expiresAt);{
"object": "api_key",
"id": "key_01H8XYZABCDEFGHJKMNPQRSTVW",
"name": "CI uploader",
"prefix": "bkt_live_aBcD",
"lastUsedAt": "2026-04-25T12:34:56Z",
"createdAt": "2026-03-01T08:00:00Z",
"permissions": ["files:write"],
"bucketIds": ["bkt_01H8XYZABCDEFGHJKMNPQRSTVW"],
"expiresAt": "2026-05-01T08:00:00Z"
}delete
keys.deleteDELETE/v1/keys/{id}keys.delete(id: string): Promise<WriteResponse<"api_key">>Revokes the key immediately — there is no grace period. To rotate without
downtime, mint the replacement first, deploy it, then call delete() on
the old one.
await client.keys.delete("key_01H8XYZABCDEFGHJKMNPQRSTVW");{
"object": "api_key",
"id": "key_01H8XYZABCDEFGHJKMNPQRSTVW"
}