@dropthis/cli 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -375,11 +375,29 @@ await dropthis.auth.logout(); // 204 No Content — data is null
375
375
  ### apiKeys
376
376
 
377
377
  ```typescript
378
- await dropthis.apiKeys.create({ label: "CI" });
378
+ // Delegated key account-scoped, follows the active workspace (the default)
379
+ await dropthis.apiKeys.create({ label: "My key" });
380
+
381
+ // Delegated key restricted to specific workspaces
382
+ await dropthis.apiKeys.create({
383
+ label: "Dev only",
384
+ type: "delegated",
385
+ allowedWorkspaces: ["dev-team", "staging"],
386
+ });
387
+
388
+ // Service key pinned to one workspace — for CI/automation
389
+ await dropthis.apiKeys.create({
390
+ label: "CI deploy",
391
+ type: "service",
392
+ workspace: "prod-team",
393
+ });
394
+
379
395
  await dropthis.apiKeys.list();
380
396
  await dropthis.apiKeys.delete("key_abc123"); // 204 No Content — data is null
381
397
  ```
382
398
 
399
+ `KeyType` is `"delegated" | "service"`. A `delegated` key acts on behalf of the owning account and can switch workspaces server-side via `workspaces.use()`; a `service` key is pinned to one workspace and is intended for CI/automation where a stable target is needed.
400
+
383
401
  ### account
384
402
 
385
403
  ```typescript
@@ -443,6 +461,48 @@ await dropthis.domains.update("drops.example.com", { default: true });
443
461
  await dropthis.domains.delete("drops.example.com");
444
462
  ```
445
463
 
464
+ ### workspaces
465
+
466
+ `client.workspaces` lists and switches the active workspace for a delegated credential.
467
+
468
+ ```typescript
469
+ // All workspaces the key has access to (isActive marks the current one)
470
+ const { data } = await dropthis.workspaces.list();
471
+ for (const ws of data.data) {
472
+ console.log(ws.slug, ws.kind, ws.isActive);
473
+ }
474
+
475
+ // The currently active workspace (null when none is active)
476
+ const { data: active } = await dropthis.workspaces.active();
477
+
478
+ // Switch the active workspace server-side (persisted on the api_keys row)
479
+ await dropthis.workspaces.use("team-slug"); // slug or id
480
+ ```
481
+
482
+ `workspaces.use()` only applies to `delegated` keys; `service` keys are pinned at creation.
483
+
484
+ #### Targeting a workspace on publish
485
+
486
+ Pass `workspace` in the publish options to target a specific workspace for that call:
487
+
488
+ ```typescript
489
+ const { data } = await dropthis.drops.publish("<h1>Team report</h1>", {
490
+ workspace: "team-slug",
491
+ });
492
+ console.log(data.workspace); // { id, name, slug, kind } — owning workspace echoed on every drop
493
+ ```
494
+
495
+ Set a client-level default so every publish goes to the same workspace without repeating it:
496
+
497
+ ```typescript
498
+ const dropthis = new Dropthis({ apiKey: "sk_...", workspace: "team-slug" });
499
+
500
+ // All publishes now target team-slug unless you pass a different workspace in options
501
+ const { data } = await dropthis.drops.publish("./dist");
502
+ ```
503
+
504
+ `DropthisEdge` honours the same `workspace` constructor option and publish option.
505
+
446
506
  ## Pricing tiers
447
507
 
448
508
  - **Free** — drops expire after 7 days, 5 MB per drop, 500 MB active storage, dropthis badge.
@@ -494,6 +554,8 @@ import type {
494
554
  RevokeImpact,
495
555
  CreateUploadSessionRequest,
496
556
  CreateUploadSessionResponse,
557
+ Workspace,
558
+ DropWorkspace,
497
559
  } from "@dropthis/node";
498
560
  ```
499
561
 
@@ -4,6 +4,12 @@ type DropthisClientOptions = {
4
4
  timeoutMs?: number;
5
5
  uploadTimeoutMs?: number;
6
6
  fetch?: typeof globalThis.fetch;
7
+ /**
8
+ * Default workspace slug or id applied to every publish/prepare call that
9
+ * does not supply its own `options.workspace`. Delegated credentials only;
10
+ * ignored by pinned service keys.
11
+ */
12
+ workspace?: string;
7
13
  };
8
14
  type RequestOptions = {
9
15
  authenticated?: boolean;
@@ -57,6 +63,17 @@ type TierInfo = {
57
63
  type Limitations = {
58
64
  actions: DropAction[];
59
65
  };
66
+ /**
67
+ * Workspace context echoed on every drop response. Identifies which workspace
68
+ * the drop was published into (ADR 0066).
69
+ */
70
+ type DropWorkspace = {
71
+ id: string;
72
+ name: string;
73
+ slug: string;
74
+ /** `personal` for a solo workspace, `team` for a shared team workspace. */
75
+ kind: string;
76
+ };
60
77
  type DropResponse = {
61
78
  id: string;
62
79
  slug: string;
@@ -100,6 +117,8 @@ type DropResponse = {
100
117
  * To stream bytes through the SDK regardless of drop kind, use `drops.getContent()`.
101
118
  */
102
119
  rawUrl: string | null;
120
+ /** The workspace this drop belongs to (echoed from the server on every response). */
121
+ workspace: DropWorkspace;
103
122
  };
104
123
  type DropDeploymentResponse = {
105
124
  id: string;
@@ -163,11 +182,11 @@ type SessionResponse = {
163
182
  refreshToken?: string | null;
164
183
  };
165
184
  /**
166
- * Why an API key exists. `standard` keys are created by the user (CLI/SDK/manual);
167
- * `mcp_oauth` keys are minted per connected client by the MCP OAuth flow and carry a
168
- * more generous quota.
185
+ * Why an API key exists. `delegated` keys act on behalf of the owning account (scoped
186
+ * to the active workspace or an allowed set); `service` keys are pinned to a single
187
+ * workspace and are intended for CI/automation.
169
188
  */
170
- type KeyType = "standard" | "mcp_oauth";
189
+ type KeyType = "delegated" | "service";
171
190
  /** What breaks when a key is revoked. */
172
191
  type RevokeImpact = "disconnects_app" | "breaks_automation";
173
192
  type ApiKeyResponse = {
@@ -222,6 +241,23 @@ type AccountWorkspace = {
222
241
  /** The calling account's role in this workspace: `owner`, `admin`, or `member`. */
223
242
  role: string;
224
243
  };
244
+ /**
245
+ * A workspace the caller belongs to or has delegated access to.
246
+ * Returned by `GET /v1/workspaces` and `PUT /v1/account/active-workspace`.
247
+ */
248
+ type Workspace = {
249
+ id: string;
250
+ name: string;
251
+ slug: string;
252
+ /** `personal` for a solo workspace, `team` for a shared team workspace. */
253
+ kind: string;
254
+ /** The calling account's role in this workspace: `owner`, `admin`, or `member`. */
255
+ role: string;
256
+ /** The plan tier of this workspace. */
257
+ plan: string;
258
+ /** Whether this workspace is currently the caller's active workspace. */
259
+ isActive: boolean;
260
+ };
225
261
  type AccountResponse = {
226
262
  id: string;
227
263
  email: string;
@@ -273,6 +309,12 @@ type CreateUploadSessionRequest = {
273
309
  schemaVersion?: 1;
274
310
  files: UploadManifestFile[];
275
311
  entry?: string | null;
312
+ /**
313
+ * Target workspace slug or id for this upload session. Delegated credentials only;
314
+ * ignored by pinned service keys. Bound at session creation and inherited by the
315
+ * subsequent POST /drops call.
316
+ */
317
+ workspace?: string;
276
318
  };
277
319
  type UploadTarget = {
278
320
  /** Always `single_put` — one signed PUT per file is the upload contract. */
@@ -372,7 +414,16 @@ type RequestControls = {
372
414
  /** Fail if current revision doesn't match -- optimistic lock (update only). */
373
415
  ifRevision?: number;
374
416
  };
375
- type PublishOptions = DropOptions & PrepareOptions & RequestControls;
417
+ type PublishOptions = DropOptions & PrepareOptions & RequestControls & {
418
+ /**
419
+ * Target workspace slug or id — publish/prepare only (a fresh drop's workspace).
420
+ * Delegated credentials only; ignored by pinned service keys. Falls back to the
421
+ * client-level `workspace` default when omitted. Not a settings field: it is NOT
422
+ * accepted by `updateSettings` (a drop never moves workspace) nor by `updateContent`
423
+ * (which stays in the drop's own workspace).
424
+ */
425
+ workspace?: string;
426
+ };
376
427
  /**
377
428
  * Options for `drops.updateContent()` — content-only. A content update ships a new content version
378
429
  * and never changes drop settings (title, visibility, password, noindex, expiry, metadata); those
@@ -642,11 +693,15 @@ type PreparedPublishRequest = {
642
693
  files: PreparedUploadFile[];
643
694
  options: Record<string, unknown>;
644
695
  metadata?: Record<string, unknown>;
696
+ /** Target workspace slug or id (delegated credentials only). Bound at upload-session creation. */
697
+ workspace?: string;
645
698
  } | {
646
699
  kind: "source";
647
700
  sourceUrl: string;
648
701
  options: Record<string, unknown>;
649
702
  metadata?: Record<string, unknown>;
703
+ /** Target workspace slug or id (delegated credentials only). Forwarded as top-level field in POST /drops. */
704
+ workspace?: string;
650
705
  };
651
706
  /**
652
707
  * The canonical publish inputs that can be resolved with no filesystem access:
@@ -686,6 +741,12 @@ declare class ApiKeysResource {
686
741
  }>>;
687
742
  create(input: {
688
743
  label: string;
744
+ /** Key type: `"delegated"` (default on server) or `"service"` (pinned to a workspace). */
745
+ type?: KeyType;
746
+ /** Pin a `service` key to this workspace slug or id. */
747
+ workspace?: string;
748
+ /** Restrict a `delegated` key to these workspace slugs or ids. */
749
+ allowedWorkspaces?: string[];
689
750
  }): Promise<DropthisResult<ApiKeyCreatedResponse>>;
690
751
  /** Revoke an API key. 204 No Content — data is null on success. */
691
752
  delete(keyId: string): Promise<DropthisResult<null>>;
@@ -776,7 +837,8 @@ declare class CursorPage<T> implements ListPage<T> {
776
837
  declare class DropsResource<TInput = PublishInput> {
777
838
  private readonly transport;
778
839
  private readonly resolveInput;
779
- constructor(transport: Transport, resolveInput: PublishInputResolver<TInput>);
840
+ private readonly defaultWorkspace?;
841
+ constructor(transport: Transport, resolveInput: PublishInputResolver<TInput>, defaultWorkspace?: string | undefined);
780
842
  /**
781
843
  * Publish content to a NEW permanent public URL; returns the created drop (with its `drop_…` id).
782
844
  * Use to publish / share / post / put online / make public a report, dashboard, site, or file.
@@ -852,4 +914,4 @@ declare class DropsResource<TInput = PublishInput> {
852
914
  delete(dropId: string): Promise<DropthisResult<null>>;
853
915
  }
854
916
 
855
- export { type AccountLimits as A, type PreparedPublishRequest as B, type CreateUploadSessionRequest as C, type DeploymentContentFile as D, type EmailOtpResponse as E, type PreparedUploadFile as F, type GetContentOptions as G, type PublishFileInput as H, type InMemoryPublishInput as I, type PublishInput as J, type KeyType as K, type Limitations as L, type PublishOptions as M, type NextHint as N, type RequestOptions as O, type PrepareOptions as P, type RevokeImpact as Q, type RequestControls as R, SHARED_POOL as S, type SessionResponse as T, type TierInfo as U, Transport as V, type UpdateContentOptions as W, type UploadManifestFile as X, type UploadSessionFileResponse as Y, type UploadSessionResponse as Z, type UploadTarget as _, AccountResource as a, type AccountResponse as b, type AccountWorkspace as c, type ActionResolve as d, ApiKeysResource as e, type CreateUploadSessionResponse as f, CursorPage as g, type DeploymentContentManifest as h, DeploymentsResource as i, type DnsRecord as j, type DomainDeletedResponse as k, type DomainListResponse as l, type DomainResponse as m, DomainsResource as n, type DropAction as o, type DropContentFile as p, type DropDeploymentResponse as q, type DropOptions as r, type DropResponse as s, DropsResource as t, type DropthisClientOptions as u, type DropthisErrorResponse as v, type DropthisResult as w, type ListDeploymentsParams as x, type ListDeploymentsResponse as y, type ListPage as z };
917
+ export { type UploadTarget as $, type AccountLimits as A, type ListPage as B, type CreateUploadSessionRequest as C, type DeploymentContentFile as D, type EmailOtpResponse as E, type PreparedPublishRequest as F, type GetContentOptions as G, type PreparedUploadFile as H, type InMemoryPublishInput as I, type PublishFileInput as J, type KeyType as K, type Limitations as L, type PublishInput as M, type NextHint as N, type PublishOptions as O, type PrepareOptions as P, type RequestOptions as Q, type RequestControls as R, type RevokeImpact as S, SHARED_POOL as T, type SessionResponse as U, type TierInfo as V, Transport as W, type UpdateContentOptions as X, type UploadManifestFile as Y, type UploadSessionFileResponse as Z, type UploadSessionResponse as _, AccountResource as a, type Workspace as a0, type AccountResponse as b, type AccountWorkspace as c, type ActionResolve as d, ApiKeysResource as e, type CreateUploadSessionResponse as f, CursorPage as g, type DeploymentContentManifest as h, DeploymentsResource as i, type DnsRecord as j, type DomainDeletedResponse as k, type DomainListResponse as l, type DomainResponse as m, DomainsResource as n, type DropAction as o, type DropContentFile as p, type DropDeploymentResponse as q, type DropOptions as r, type DropResponse as s, type DropWorkspace as t, DropsResource as u, type DropthisClientOptions as v, type DropthisErrorResponse as w, type DropthisResult as x, type ListDeploymentsParams as y, type ListDeploymentsResponse as z };
@@ -4,6 +4,12 @@ type DropthisClientOptions = {
4
4
  timeoutMs?: number;
5
5
  uploadTimeoutMs?: number;
6
6
  fetch?: typeof globalThis.fetch;
7
+ /**
8
+ * Default workspace slug or id applied to every publish/prepare call that
9
+ * does not supply its own `options.workspace`. Delegated credentials only;
10
+ * ignored by pinned service keys.
11
+ */
12
+ workspace?: string;
7
13
  };
8
14
  type RequestOptions = {
9
15
  authenticated?: boolean;
@@ -57,6 +63,17 @@ type TierInfo = {
57
63
  type Limitations = {
58
64
  actions: DropAction[];
59
65
  };
66
+ /**
67
+ * Workspace context echoed on every drop response. Identifies which workspace
68
+ * the drop was published into (ADR 0066).
69
+ */
70
+ type DropWorkspace = {
71
+ id: string;
72
+ name: string;
73
+ slug: string;
74
+ /** `personal` for a solo workspace, `team` for a shared team workspace. */
75
+ kind: string;
76
+ };
60
77
  type DropResponse = {
61
78
  id: string;
62
79
  slug: string;
@@ -100,6 +117,8 @@ type DropResponse = {
100
117
  * To stream bytes through the SDK regardless of drop kind, use `drops.getContent()`.
101
118
  */
102
119
  rawUrl: string | null;
120
+ /** The workspace this drop belongs to (echoed from the server on every response). */
121
+ workspace: DropWorkspace;
103
122
  };
104
123
  type DropDeploymentResponse = {
105
124
  id: string;
@@ -163,11 +182,11 @@ type SessionResponse = {
163
182
  refreshToken?: string | null;
164
183
  };
165
184
  /**
166
- * Why an API key exists. `standard` keys are created by the user (CLI/SDK/manual);
167
- * `mcp_oauth` keys are minted per connected client by the MCP OAuth flow and carry a
168
- * more generous quota.
185
+ * Why an API key exists. `delegated` keys act on behalf of the owning account (scoped
186
+ * to the active workspace or an allowed set); `service` keys are pinned to a single
187
+ * workspace and are intended for CI/automation.
169
188
  */
170
- type KeyType = "standard" | "mcp_oauth";
189
+ type KeyType = "delegated" | "service";
171
190
  /** What breaks when a key is revoked. */
172
191
  type RevokeImpact = "disconnects_app" | "breaks_automation";
173
192
  type ApiKeyResponse = {
@@ -222,6 +241,23 @@ type AccountWorkspace = {
222
241
  /** The calling account's role in this workspace: `owner`, `admin`, or `member`. */
223
242
  role: string;
224
243
  };
244
+ /**
245
+ * A workspace the caller belongs to or has delegated access to.
246
+ * Returned by `GET /v1/workspaces` and `PUT /v1/account/active-workspace`.
247
+ */
248
+ type Workspace = {
249
+ id: string;
250
+ name: string;
251
+ slug: string;
252
+ /** `personal` for a solo workspace, `team` for a shared team workspace. */
253
+ kind: string;
254
+ /** The calling account's role in this workspace: `owner`, `admin`, or `member`. */
255
+ role: string;
256
+ /** The plan tier of this workspace. */
257
+ plan: string;
258
+ /** Whether this workspace is currently the caller's active workspace. */
259
+ isActive: boolean;
260
+ };
225
261
  type AccountResponse = {
226
262
  id: string;
227
263
  email: string;
@@ -273,6 +309,12 @@ type CreateUploadSessionRequest = {
273
309
  schemaVersion?: 1;
274
310
  files: UploadManifestFile[];
275
311
  entry?: string | null;
312
+ /**
313
+ * Target workspace slug or id for this upload session. Delegated credentials only;
314
+ * ignored by pinned service keys. Bound at session creation and inherited by the
315
+ * subsequent POST /drops call.
316
+ */
317
+ workspace?: string;
276
318
  };
277
319
  type UploadTarget = {
278
320
  /** Always `single_put` — one signed PUT per file is the upload contract. */
@@ -372,7 +414,16 @@ type RequestControls = {
372
414
  /** Fail if current revision doesn't match -- optimistic lock (update only). */
373
415
  ifRevision?: number;
374
416
  };
375
- type PublishOptions = DropOptions & PrepareOptions & RequestControls;
417
+ type PublishOptions = DropOptions & PrepareOptions & RequestControls & {
418
+ /**
419
+ * Target workspace slug or id — publish/prepare only (a fresh drop's workspace).
420
+ * Delegated credentials only; ignored by pinned service keys. Falls back to the
421
+ * client-level `workspace` default when omitted. Not a settings field: it is NOT
422
+ * accepted by `updateSettings` (a drop never moves workspace) nor by `updateContent`
423
+ * (which stays in the drop's own workspace).
424
+ */
425
+ workspace?: string;
426
+ };
376
427
  /**
377
428
  * Options for `drops.updateContent()` — content-only. A content update ships a new content version
378
429
  * and never changes drop settings (title, visibility, password, noindex, expiry, metadata); those
@@ -642,11 +693,15 @@ type PreparedPublishRequest = {
642
693
  files: PreparedUploadFile[];
643
694
  options: Record<string, unknown>;
644
695
  metadata?: Record<string, unknown>;
696
+ /** Target workspace slug or id (delegated credentials only). Bound at upload-session creation. */
697
+ workspace?: string;
645
698
  } | {
646
699
  kind: "source";
647
700
  sourceUrl: string;
648
701
  options: Record<string, unknown>;
649
702
  metadata?: Record<string, unknown>;
703
+ /** Target workspace slug or id (delegated credentials only). Forwarded as top-level field in POST /drops. */
704
+ workspace?: string;
650
705
  };
651
706
  /**
652
707
  * The canonical publish inputs that can be resolved with no filesystem access:
@@ -686,6 +741,12 @@ declare class ApiKeysResource {
686
741
  }>>;
687
742
  create(input: {
688
743
  label: string;
744
+ /** Key type: `"delegated"` (default on server) or `"service"` (pinned to a workspace). */
745
+ type?: KeyType;
746
+ /** Pin a `service` key to this workspace slug or id. */
747
+ workspace?: string;
748
+ /** Restrict a `delegated` key to these workspace slugs or ids. */
749
+ allowedWorkspaces?: string[];
689
750
  }): Promise<DropthisResult<ApiKeyCreatedResponse>>;
690
751
  /** Revoke an API key. 204 No Content — data is null on success. */
691
752
  delete(keyId: string): Promise<DropthisResult<null>>;
@@ -776,7 +837,8 @@ declare class CursorPage<T> implements ListPage<T> {
776
837
  declare class DropsResource<TInput = PublishInput> {
777
838
  private readonly transport;
778
839
  private readonly resolveInput;
779
- constructor(transport: Transport, resolveInput: PublishInputResolver<TInput>);
840
+ private readonly defaultWorkspace?;
841
+ constructor(transport: Transport, resolveInput: PublishInputResolver<TInput>, defaultWorkspace?: string | undefined);
780
842
  /**
781
843
  * Publish content to a NEW permanent public URL; returns the created drop (with its `drop_…` id).
782
844
  * Use to publish / share / post / put online / make public a report, dashboard, site, or file.
@@ -852,4 +914,4 @@ declare class DropsResource<TInput = PublishInput> {
852
914
  delete(dropId: string): Promise<DropthisResult<null>>;
853
915
  }
854
916
 
855
- export { type AccountLimits as A, type PreparedPublishRequest as B, type CreateUploadSessionRequest as C, type DeploymentContentFile as D, type EmailOtpResponse as E, type PreparedUploadFile as F, type GetContentOptions as G, type PublishFileInput as H, type InMemoryPublishInput as I, type PublishInput as J, type KeyType as K, type Limitations as L, type PublishOptions as M, type NextHint as N, type RequestOptions as O, type PrepareOptions as P, type RevokeImpact as Q, type RequestControls as R, SHARED_POOL as S, type SessionResponse as T, type TierInfo as U, Transport as V, type UpdateContentOptions as W, type UploadManifestFile as X, type UploadSessionFileResponse as Y, type UploadSessionResponse as Z, type UploadTarget as _, AccountResource as a, type AccountResponse as b, type AccountWorkspace as c, type ActionResolve as d, ApiKeysResource as e, type CreateUploadSessionResponse as f, CursorPage as g, type DeploymentContentManifest as h, DeploymentsResource as i, type DnsRecord as j, type DomainDeletedResponse as k, type DomainListResponse as l, type DomainResponse as m, DomainsResource as n, type DropAction as o, type DropContentFile as p, type DropDeploymentResponse as q, type DropOptions as r, type DropResponse as s, DropsResource as t, type DropthisClientOptions as u, type DropthisErrorResponse as v, type DropthisResult as w, type ListDeploymentsParams as x, type ListDeploymentsResponse as y, type ListPage as z };
917
+ export { type UploadTarget as $, type AccountLimits as A, type ListPage as B, type CreateUploadSessionRequest as C, type DeploymentContentFile as D, type EmailOtpResponse as E, type PreparedPublishRequest as F, type GetContentOptions as G, type PreparedUploadFile as H, type InMemoryPublishInput as I, type PublishFileInput as J, type KeyType as K, type Limitations as L, type PublishInput as M, type NextHint as N, type PublishOptions as O, type PrepareOptions as P, type RequestOptions as Q, type RequestControls as R, type RevokeImpact as S, SHARED_POOL as T, type SessionResponse as U, type TierInfo as V, Transport as W, type UpdateContentOptions as X, type UploadManifestFile as Y, type UploadSessionFileResponse as Z, type UploadSessionResponse as _, AccountResource as a, type Workspace as a0, type AccountResponse as b, type AccountWorkspace as c, type ActionResolve as d, ApiKeysResource as e, type CreateUploadSessionResponse as f, CursorPage as g, type DeploymentContentManifest as h, DeploymentsResource as i, type DnsRecord as j, type DomainDeletedResponse as k, type DomainListResponse as l, type DomainResponse as m, DomainsResource as n, type DropAction as o, type DropContentFile as p, type DropDeploymentResponse as q, type DropOptions as r, type DropResponse as s, type DropWorkspace as t, DropsResource as u, type DropthisClientOptions as v, type DropthisErrorResponse as w, type DropthisResult as x, type ListDeploymentsParams as y, type ListDeploymentsResponse as z };
@@ -253,7 +253,8 @@ function buildStagedRequest(files, options, entry) {
253
253
  const manifest = {
254
254
  schemaVersion: 1,
255
255
  files: manifestFiles,
256
- ...resolvedEntry ? { entry: resolvedEntry } : {}
256
+ ...resolvedEntry ? { entry: resolvedEntry } : {},
257
+ ...options.workspace !== void 0 ? { workspace: options.workspace } : {}
257
258
  };
258
259
  const prepared = {
259
260
  kind: "staged",
@@ -262,6 +263,7 @@ function buildStagedRequest(files, options, entry) {
262
263
  options: optionsBody(options)
263
264
  };
264
265
  if (options.metadata) prepared.metadata = options.metadata;
266
+ if (options.workspace !== void 0) prepared.workspace = options.workspace;
265
267
  return prepared;
266
268
  }
267
269
  function buildSourceRequest(sourceUrl, options) {
@@ -279,6 +281,7 @@ function buildSourceRequest(sourceUrl, options) {
279
281
  options: optionsBody(options)
280
282
  };
281
283
  if (options.metadata) prepared.metadata = options.metadata;
284
+ if (options.workspace !== void 0) prepared.workspace = options.workspace;
282
285
  return prepared;
283
286
  }
284
287
  function decodeBase64(value) {
@@ -503,6 +506,7 @@ async function publishSource(transport, prepared, finalPath, options = {}) {
503
506
  sourceUrl: prepared.sourceUrl,
504
507
  ...Object.keys(prepared.options).length > 0 ? { options: prepared.options } : {},
505
508
  ...prepared.metadata ? { metadata: prepared.metadata } : {},
509
+ ...prepared.workspace !== void 0 ? { workspace: prepared.workspace } : {},
506
510
  ...partialUpdateBody(options)
507
511
  },
508
512
  idempotencyKey: `${baseKey}:publish`,
@@ -537,7 +541,12 @@ var ApiKeysResource = class {
537
541
  return this.transport.request("GET", "/api-keys");
538
542
  }
539
543
  create(input) {
540
- return this.transport.request("POST", "/api-keys", { body: input });
544
+ const body = { label: input.label };
545
+ if (input.type !== void 0) body.key_type = input.type;
546
+ if (input.workspace !== void 0) body.workspace = input.workspace;
547
+ if (input.allowedWorkspaces !== void 0)
548
+ body.allowed_workspace_ids = input.allowedWorkspaces;
549
+ return this.transport.request("POST", "/api-keys", { body });
541
550
  }
542
551
  /** Revoke an API key. 204 No Content — data is null on success. */
543
552
  delete(keyId) {
@@ -685,12 +694,14 @@ var CursorPage = class {
685
694
 
686
695
  // src/resources/drops.ts
687
696
  var DropsResource = class {
688
- constructor(transport, resolveInput) {
697
+ constructor(transport, resolveInput, defaultWorkspace) {
689
698
  this.transport = transport;
690
699
  this.resolveInput = resolveInput;
700
+ this.defaultWorkspace = defaultWorkspace;
691
701
  }
692
702
  transport;
693
703
  resolveInput;
704
+ defaultWorkspace;
694
705
  /**
695
706
  * Publish content to a NEW permanent public URL; returns the created drop (with its `drop_…` id).
696
707
  * Use to publish / share / post / put online / make public a report, dashboard, site, or file.
@@ -708,13 +719,14 @@ var DropsResource = class {
708
719
  * collections. To stream bytes through the SDK for any drop kind, use {@link getContent}.
709
720
  */
710
721
  async publish(input, options = {}) {
722
+ const merged = this.defaultWorkspace !== void 0 && options.workspace === void 0 ? { ...options, workspace: this.defaultWorkspace } : options;
711
723
  let prepared;
712
724
  try {
713
- prepared = await this.resolveInput(input, options);
725
+ prepared = await this.resolveInput(input, merged);
714
726
  } catch (e) {
715
727
  return toErrorResult(e);
716
728
  }
717
- return prepared.kind === "source" ? publishSource(this.transport, prepared, "/drops", options) : publishStaged(this.transport, prepared, "/drops", options);
729
+ return prepared.kind === "source" ? publishSource(this.transport, prepared, "/drops", merged) : publishStaged(this.transport, prepared, "/drops", merged);
718
730
  }
719
731
  /**
720
732
  * Replace the content of an EXISTING drop, keeping its URL (ships a new deployment). Requires the
@@ -892,7 +904,7 @@ function toSnakeCase(value) {
892
904
 
893
905
  // src/transport.ts
894
906
  var DEFAULT_BASE_URL = "https://api.dropthis.app";
895
- var SDK_VERSION = "0.23.0";
907
+ var SDK_VERSION = "0.24.0";
896
908
  var Transport = class {
897
909
  apiKey;
898
910
  baseUrl;
@@ -1132,6 +1144,8 @@ function booleanValue(value) {
1132
1144
  // src/edge.ts
1133
1145
  var DropthisEdge = class {
1134
1146
  transport;
1147
+ /** Client-level workspace default; applied when a publish call omits `options.workspace`. */
1148
+ defaultWorkspace;
1135
1149
  dropsResource;
1136
1150
  accountResource;
1137
1151
  apiKeysResource;
@@ -1139,10 +1153,15 @@ var DropthisEdge = class {
1139
1153
  domainsResource;
1140
1154
  constructor(options = {}) {
1141
1155
  this.transport = new Transport(options);
1156
+ this.defaultWorkspace = typeof options === "string" ? void 0 : options.workspace;
1142
1157
  }
1143
1158
  get drops() {
1144
1159
  if (!this.dropsResource)
1145
- this.dropsResource = new DropsResource(this.transport, resolveInMemory);
1160
+ this.dropsResource = new DropsResource(
1161
+ this.transport,
1162
+ resolveInMemory,
1163
+ this.defaultWorkspace
1164
+ );
1146
1165
  return this.dropsResource;
1147
1166
  }
1148
1167
  get account() {