@fusebase/fusebase-gate-sdk 2.4.0 → 2.5.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.
@@ -5,7 +5,7 @@
5
5
  * Domain: fusebase-auth
6
6
  */
7
7
  import type { Client } from "../runtime/transport";
8
- import type { FusebaseAuthChallengeRequestContract, FusebaseAuthChallengeResponseContract, FusebaseAuthLoginRequestContract, FusebaseAuthLoginResponseContract, FusebaseAuthLogoutResponseContract, FusebaseAuthPasswordResetRequestContract, FusebaseAuthPasswordResetResponseContract, FusebaseAuthPasswordRestoreKeyResponseContract, FusebaseAuthPasswordRestoreRequestContract, FusebaseAuthPasswordRestoreResponseContract, FusebaseAuthRegisterMemberRequestContract, FusebaseAuthRegisterMemberResponseContract, FusebaseAuthRegisterRequestContract, FusebaseAuthRegisterResponseContract, FusebaseAuthRestoreKeyRequestContract, FusebaseAuthRestoreKeyResponseContract, orgIdInPathRequired } from "../types";
8
+ import type { FusebaseAuthChallengeRequestContract, FusebaseAuthChallengeResponseContract, FusebaseAuthLoginRequestContract, FusebaseAuthLoginResponseContract, FusebaseAuthLogoutResponseContract, FusebaseAuthPasswordResetRequestContract, FusebaseAuthPasswordResetResponseContract, FusebaseAuthPasswordRestoreKeyResponseContract, FusebaseAuthPasswordRestoreRequestContract, FusebaseAuthPasswordRestoreResponseContract, FusebaseAuthRegisterMemberRequestContract, FusebaseAuthRegisterMemberResponseContract, FusebaseAuthRegisterRequestContract, FusebaseAuthRegisterResponseContract, FusebaseAuthRestoreKeyRequestContract, FusebaseAuthRestoreKeyResponseContract, FusebaseAuthSetInitialPasswordRequestContract, FusebaseAuthSetInitialPasswordResponseContract, orgIdInPathRequired } from "../types";
9
9
  export declare class FusebaseAuthApi {
10
10
  private client;
11
11
  constructor(client: Client);
@@ -91,4 +91,12 @@ export declare class FusebaseAuthApi {
91
91
  headers?: Record<string, string>;
92
92
  body: FusebaseAuthPasswordResetRequestContract;
93
93
  }): Promise<FusebaseAuthPasswordResetResponseContract>;
94
+ /**
95
+ * Set the initial password of the calling invited account
96
+ * Sets the password of the authenticated caller, once, without any platform email. Needed for an invitee whose account was pre-provisioned by an invite (`addOrgUser` with autoConfirmClientInvite, or an app magic link) and therefore holds a random password its user never learns. Limits: the subject is always the caller — there is no email in the body and a service/app-token caller gets 403; `409` once a password has been set, so an existing user's password can never be overwritten (use password restore for that); no session is minted and every existing session of the account is dropped, so the user must sign in with the new password afterwards.
97
+ */
98
+ setFusebaseInitialPassword(params: {
99
+ headers?: Record<string, string>;
100
+ body: FusebaseAuthSetInitialPasswordRequestContract;
101
+ }): Promise<FusebaseAuthSetInitialPasswordResponseContract>;
94
102
  }
@@ -139,5 +139,19 @@ class FusebaseAuthApi {
139
139
  expectedContentType: "application/json",
140
140
  });
141
141
  }
142
+ /**
143
+ * Set the initial password of the calling invited account
144
+ * Sets the password of the authenticated caller, once, without any platform email. Needed for an invitee whose account was pre-provisioned by an invite (`addOrgUser` with autoConfirmClientInvite, or an app magic link) and therefore holds a random password its user never learns. Limits: the subject is always the caller — there is no email in the body and a service/app-token caller gets 403; `409` once a password has been set, so an existing user's password can never be overwritten (use password restore for that); no session is minted and every existing session of the account is dropped, so the user must sign in with the new password afterwards.
145
+ */
146
+ async setFusebaseInitialPassword(params) {
147
+ return this.client.request({
148
+ method: "POST",
149
+ path: "/auth/fusebase/set-initial-password",
150
+ headers: params.headers,
151
+ body: params.body,
152
+ opId: "setFusebaseInitialPassword",
153
+ expectedContentType: "application/json",
154
+ });
155
+ }
142
156
  }
143
157
  exports.FusebaseAuthApi = FusebaseAuthApi;
@@ -11,7 +11,7 @@ export declare class PortalFeatureContextApi {
11
11
  constructor(client: Client);
12
12
  /**
13
13
  * Verify portal embed context token
14
- * Validates a platform-signed `portalFeatureContextToken` (iframe query param) and returns trusted portalId/workspaceId for backend RLS context. The token must match the path appId when bound to a specific app feature.
14
+ * Validates a platform-signed `portalFeatureContextToken` (iframe query param) and returns trusted portalId/workspaceId for backend RLS context. The token must match the path appId when bound to a specific app feature. Additionally returns the caller's `userId`/`orgRole` if and only if the request is authenticated with an app session whose own portal binding equals the verified token's portalId AND the caller is a real user, not an anonymous visitor — i.e. they opened this app through THIS portal's embed. Identity is never read from the token itself: it is static, shared by all viewers of the brick and user-agnostic. Presence of `userId` proves the platform bound this user to this portal and app; it does NOT prove portal membership (enforce that via the app's `--access` principals).
15
15
  */
16
16
  verifyPortalFeatureContextToken(params: {
17
17
  path: {
@@ -13,7 +13,7 @@ class PortalFeatureContextApi {
13
13
  }
14
14
  /**
15
15
  * Verify portal embed context token
16
- * Validates a platform-signed `portalFeatureContextToken` (iframe query param) and returns trusted portalId/workspaceId for backend RLS context. The token must match the path appId when bound to a specific app feature.
16
+ * Validates a platform-signed `portalFeatureContextToken` (iframe query param) and returns trusted portalId/workspaceId for backend RLS context. The token must match the path appId when bound to a specific app feature. Additionally returns the caller's `userId`/`orgRole` if and only if the request is authenticated with an app session whose own portal binding equals the verified token's portalId AND the caller is a real user, not an anonymous visitor — i.e. they opened this app through THIS portal's embed. Identity is never read from the token itself: it is static, shared by all viewers of the brick and user-agnostic. Presence of `userId` proves the platform bound this user to this portal and app; it does NOT prove portal membership (enforce that via the app's `--access` principals).
17
17
  */
18
18
  async verifyPortalFeatureContextToken(params) {
19
19
  return this.client.request({
@@ -5,10 +5,23 @@
5
5
  * Domain: portals
6
6
  */
7
7
  import type { Client } from "../runtime/transport";
8
- import type { AddPortalAppBlockRequestContract, AddPortalAppBlockResponseContract, AddPortalAppPageRequestContract, AddPortalAppPageResponseContract, AddPortalBlankNoteBlockRequestContract, AddPortalBlankNoteBlockResponseContract, AddPortalBlockRequestContract, AddPortalBlockResponseContract, AddPortalChatBlockRequestContract, AddPortalChatBlockResponseContract, AddPortalEmbedBlockRequestContract, AddPortalEmbedBlockResponseContract, AddPortalNoteBlockRequestContract, AddPortalNoteBlockResponseContract, BulkInviteToPortalRequestContract, BulkInviteToPortalResponseContract, CreatePortalFolderRequestContract, CreatePortalFolderResponseContract, CreatePortalPageRequestContract, CreatePortalPageResponseContract, CreatePortalPageWithNoteRequestContract, CreatePortalPageWithNoteResponseContract, CreatePortalRequestContract, CreatePortalResponseContract, DuplicatePortalItemRequestContract, DuplicatePortalItemResponseContract, DuplicatePortalRequestContract, globalIdInPathRequired, InvitePortalManagerRequestContract, InvitePortalManagerResponseContract, InviteToPortalRequestContract, InviteToPortalResponseContract, ListPortalChatChannelsResponseContract, ListPortalChatUsersResponseContract, ListPortalContentResponseContract, orgIdInPathRequired, OrgPortalListResponseContract, PortalDetailContract, PublishPortalDraftResponseContract, UpdatePortalAccessRequestContract, UpdatePortalAccessResponseContract, UpdatePortalCustomCodeRequestContract, UpdatePortalCustomCodeResponseContract } from "../types";
8
+ import type { AddPortalAiAgentBlockRequestContract, AddPortalAiAgentBlockResponseContract, AddPortalAppBlockRequestContract, AddPortalAppBlockResponseContract, AddPortalAppPageRequestContract, AddPortalAppPageResponseContract, AddPortalBlankNoteBlockRequestContract, AddPortalBlankNoteBlockResponseContract, AddPortalBlockRequestContract, AddPortalBlockResponseContract, AddPortalCardBlockRequestContract, AddPortalCardBlockResponseContract, AddPortalCarouselBlockRequestContract, AddPortalCarouselBlockResponseContract, AddPortalChatBlockRequestContract, AddPortalChatBlockResponseContract, AddPortalCountdownBlockRequestContract, AddPortalCountdownBlockResponseContract, AddPortalDatabaseBlockRequestContract, AddPortalDatabaseBlockResponseContract, AddPortalEmbedBlockRequestContract, AddPortalEmbedBlockResponseContract, AddPortalHeadingBlockRequestContract, AddPortalImageBlockRequestContract, AddPortalNoteBlockRequestContract, AddPortalNoteBlockResponseContract, AddPortalTextBlockRequestContract, BulkInviteToPortalRequestContract, BulkInviteToPortalResponseContract, CreatePortalFolderRequestContract, CreatePortalFolderResponseContract, CreatePortalPageRequestContract, CreatePortalPageResponseContract, CreatePortalPageWithNoteRequestContract, CreatePortalPageWithNoteResponseContract, CreatePortalRequestContract, CreatePortalResponseContract, DuplicatePortalItemRequestContract, DuplicatePortalItemResponseContract, DuplicatePortalRequestContract, GetPortalPageBlockCountResponseContract, globalIdInPathRequired, InvitePortalManagerRequestContract, InvitePortalManagerResponseContract, InviteToPortalRequestContract, InviteToPortalResponseContract, ListPortalAiAgentsResponseContract, ListPortalChatChannelsResponseContract, ListPortalChatUsersResponseContract, ListPortalContentResponseContract, ListPortalDatabaseBlockSourcesResponseContract, orgIdInPathRequired, OrgPortalListResponseContract, PortalDetailContract, PortalTextAndMediaBlockResponseContract, PublishPortalDraftResponseContract, SetDashboardViewReadonlyRequestContract, SetDashboardViewReadonlyResponseContract, UpdatePortalAccessRequestContract, UpdatePortalAccessResponseContract, UpdatePortalCustomCodeRequestContract, UpdatePortalCustomCodeResponseContract } from "../types";
9
9
  export declare class PortalsApi {
10
10
  private client;
11
11
  constructor(client: Client);
12
+ /**
13
+ * Add an AI Agent block to a portal page
14
+ * Stages one Customizer-compatible AI Agent block on an EXISTING portal page — the programmatic equivalent of the customizer's "AI Agent" tile (a flexible block with one ai-agent brick). No new page and no sidebar menu item is created. Pass only agentId, the exact id from listPortalAiAgents; the block title is the agent's current title and every layout/brick detail is fixed by the service. Immediately before calling this, check getPortalPageBlockCount with type='flexible' and templateType='ai-agent': only ONE AI Agent block is allowed per page and a second returns 400. For a published page resolve pageId from listPortalContent; for a page created earlier in the active draft use the pageId that operation returned. The block is staged in the portal's customizer draft (not published immediately). Returns the block id and the draft branch/seqs. Requires portals.write access.
15
+ */
16
+ addPortalAiAgentBlock(params: {
17
+ path: {
18
+ orgId: orgIdInPathRequired;
19
+ portalId: globalIdInPathRequired;
20
+ pageId: globalIdInPathRequired;
21
+ };
22
+ headers?: Record<string, string>;
23
+ body: AddPortalAiAgentBlockRequestContract;
24
+ }): Promise<AddPortalAiAgentBlockResponseContract>;
12
25
  /**
13
26
  * Add a published app as a block on an existing portal page
14
27
  * Stages one published Fusebase app as a flexible app-feature block on an EXISTING portal page. No new page and no sidebar menu item is created — use addPortalAppPage when the app should get its own sidebar page. Pass productId (the product that owns the app) and appId (the app to embed); resolve both, plus productType and productOrgId, with findPublishedApps. For a managed product (Customizer "Managed Products") also pass productType='managed' and productOrgId. For a published page resolve pageId from listPortalContent; for a page created earlier in the active draft use the pageId that operation returned. The block is staged in the portal's customizer draft (not published immediately). Returns the block id, the page the block was staged on, and the draft branch/seqs. Requires portals.write access.
@@ -49,7 +62,7 @@ export declare class PortalsApi {
49
62
  }): Promise<AddPortalBlankNoteBlockResponseContract>;
50
63
  /**
51
64
  * Add a block of any palette type to a portal page
52
- * Stages a single block of any supported type onto an existing portal page — the universal building block behind the customizer's 'Add new block' palette (no new page or sidebar item is created). Pass pageId (the target page node id from listPortalContent) and type. Supported types: note, content, info, docs, help, request, meetings, links, task-list, projection, files-dashboard, tasks-dashboard, chats-dashboard, files-recent, files-bucket, flexible. Type-specific fields: note/content require noteId; flexible requires template (e.g. {type:'text'|'image'|'title'|'code'|'form'|'dashboard'|'ai-agent'|'app-feature'|...}) and may carry bricks; info/projection/task-list and others take their fields via the free-form `properties` object (e.g. image/link, sourcePortalId/sourcePageId/sourceBlockId, taskListIds). This op does NOT accept type='embed' or type='chat' — use addPortalEmbedBlock for Embed blocks and addPortalChatBlock for Chat blocks. Use addPortalNoteBlock for the common note case or addPortalAppPage for an app on its own page. Note: a `content` block renames the page to its title, so leave title empty for content blocks. The block is staged in the portal's customizer draft (not published immediately); the owner reviews and publishes it. Returns the block id and the draft branch/seqs. Requires portals.write access.
65
+ * Stages a single block of any supported type onto an existing portal page — the universal building block behind the customizer's 'Add new block' palette (no new page or sidebar item is created). Pass pageId (the target page node id from listPortalContent) and type. Supported types: note, content, info, docs, help, request, meetings, links, task-list, projection, files-dashboard, tasks-dashboard, chats-dashboard, files-recent, files-bucket, flexible. Type-specific fields: note/content require noteId; flexible requires template (e.g. {type:'text'|'image'|'title'|'code'|'form'|'dashboard'|'app-feature'|...}) and may carry bricks; info/projection/task-list and others take their fields via the free-form `properties` object (e.g. image/link, sourcePortalId/sourcePageId/sourceBlockId, taskListIds). This op does NOT accept type='embed', a flexible block with template.type='dashboard' or a dashboard brick (use addPortalDatabaseBlock) or type='chat' — use addPortalEmbedBlock for Embed blocks and addPortalChatBlock for Chat blocks — and it does NOT accept a flexible ai-agent template or an ai-agent brick: use addPortalAiAgentBlock, which binds the agent to the caller. Use addPortalNoteBlock for the common note case or addPortalAppPage for an app on its own page. Note: a `content` block renames the page to its title, so leave title empty for content blocks. The block is staged in the portal's customizer draft (not published immediately); the owner reviews and publishes it. Returns the block id and the draft branch/seqs. Requires portals.write access.
53
66
  */
54
67
  addPortalBlock(params: {
55
68
  path: {
@@ -59,6 +72,32 @@ export declare class PortalsApi {
59
72
  headers?: Record<string, string>;
60
73
  body: AddPortalBlockRequestContract;
61
74
  }): Promise<AddPortalBlockResponseContract>;
75
+ /**
76
+ * Add a Card block to a portal page
77
+ * Stages one Customizer-compatible Card on an EXISTING portal page — the programmatic equivalent of the customizer's Content display "Card" tile. It creates exactly one flexible block with the five canonical bricks (Image, Heading, Description, Button, Destination URL); no page, sidebar item or media asset is created. `view` is the Card Type: `top-image`, `left-image`, `right-image` or `fill-image` (default `top-image`; `fill-image` defaults the text to white). `content` configures the bricks: `image.visible` only — the Card always uses the built-in template image and an `src`/URL/asset id/upload is rejected —, `heading` and `description` (plain text plus one palette colour token such as `cyan-700`, size `s`/`m`/`l`/`xl`, a unique set of `bold`/`italic`/`underline`/`lineThrough` styles and alignment), `button` (plain label sent as `button.text` — there is no `label` field and sending one is rejected — with no dynamic variables) and `destination`. `visible` defaults to `true`, so a visible item does NOT need `visible: true`: send `content.button: {text: "Open"}` to set an enabled Button label. Any of Image, Heading, Description and Button can be hidden with `visible: false`, which then must be the item's only field. `destination` is shared by the whole Card and its Button: an exact `pageId` of a page in THIS portal, an absolute https URL, an email address, or `null` for no link — a raw DynamicLink, `javascript:`/`data:` URL or caller-supplied internal title/targetId is rejected, and the link target (new tab) is not configurable. `appearance` is optional; omitting it keeps the Card's canonical bare wrapper, and a `custom` backdrop takes a colour, gradient or one of the five preset background images (`azure`, `mira`, `solis`, `serenity`, `glow`). `layout` sets Customizer Width (2-6, default 3) and Height (Auto by default, a manual value is at least 50px). HTML, Markdown, CSS, Tailwind classes, a wrapper title and raw bricks are not accepted. The block is staged in the portal's customizer draft (not published immediately). Requires portals.write access.
78
+ */
79
+ addPortalCardBlock(params: {
80
+ path: {
81
+ orgId: orgIdInPathRequired;
82
+ portalId: globalIdInPathRequired;
83
+ pageId: globalIdInPathRequired;
84
+ };
85
+ headers?: Record<string, string>;
86
+ body: AddPortalCardBlockRequestContract;
87
+ }): Promise<AddPortalCardBlockResponseContract>;
88
+ /**
89
+ * Add a Carousel block to a portal page
90
+ * Stages one Customizer-compatible Carousel on an EXISTING portal page — the programmatic equivalent of the customizer's Content display "Carousel" tile. It creates exactly one flexible block with a single Carousel brick; no page, sidebar item or media asset is created. Omit `content` to get the Customizer default of three slides (Deliberation, Elaboration, Presentation) with their built-in images, descriptions, More buttons and links. `content.items` replaces that list entirely and must hold 1 to 6 slides in visual order; the slide index is taken from the array position and is not accepted from the caller. Each slide takes `caption` and `description` (plain text; only `description` supports the `{{ClientName}}` and `{{ClientLastName}}` variables), `button: {text}` or `null` for no Button, and `destination` or `null` for no link — an exact `pageId` of a page in THIS portal, an absolute https URL or an email address. The slide surface and its Button share that one destination. Every slide image is a built-in one: an image/video URL, asset id, file name, base64, local path or upload is rejected, as are a raw DynamicLink, raw item index, brick, CSS class, autoplay, duration, controls and indicators. Carousel has no public Appearance settings. `layout` sets Customizer Width (2-6, default 6) and Height (Auto by default, a manual value is at least 50px). The block is staged in the portal's customizer draft (not published immediately). Requires portals.write access.
91
+ */
92
+ addPortalCarouselBlock(params: {
93
+ path: {
94
+ orgId: orgIdInPathRequired;
95
+ portalId: globalIdInPathRequired;
96
+ pageId: globalIdInPathRequired;
97
+ };
98
+ headers?: Record<string, string>;
99
+ body: AddPortalCarouselBlockRequestContract;
100
+ }): Promise<AddPortalCarouselBlockResponseContract>;
62
101
  /**
63
102
  * Add a Chat block to a portal page
64
103
  * Stages one Customizer-compatible Chat block on an EXISTING portal page — the programmatic equivalent of the customizer's "Chat" action. Pass exactly one target: { type: 'channel', channelId } (id from listPortalChatChannels) or { type: 'dm', userId } (an active org member's userId). membersOnly is channel-only (default true; a private channel requires true; forbidden for dm). One active Chat block is allowed per page — a second returns 409. Creates one chat widget configuration and stages the block in the customizer draft (not published immediately). This is a Chat WIDGET on a page, distinct from the portal's system chat menu item and the chats-dashboard block. For a published page resolve pageId from listPortalContent; for a page created earlier in the active draft use the pageId that operation returned. Returns the block id and the draft branch/seqs. Requires portals.write access.
@@ -72,6 +111,32 @@ export declare class PortalsApi {
72
111
  headers?: Record<string, string>;
73
112
  body: AddPortalChatBlockRequestContract;
74
113
  }): Promise<AddPortalChatBlockResponseContract>;
114
+ /**
115
+ * Add a Countdown block to a portal page
116
+ * Stages one Customizer-compatible Countdown on an EXISTING portal page — the programmatic equivalent of the customizer's Content display "Countdown" tile. It creates exactly one flexible block with a single Countdown item that ticks down days, hours, minutes and seconds to a future moment; no page, sidebar item or external entity is created. The body may be empty, which reproduces the Customizer default: the title "Countdown" and a target 30 days after creation. `content.targetAt` is an absolute RFC 3339 date-time with `Z` or an explicit UTC offset — epoch seconds/milliseconds, a timezone-less local date and a duration are rejected, as are a raw timestamp, brick, renderer style, the item's internal title and its fixed days/hours/min/sec labels. The target must not be in the past or more than 99 days after creation. `title` is the block title (plain text, only the `{{ClientName}}` and `{{ClientLastName}}` variables). `appearance` sets Customizer Backdrop `none`, `blank` or `custom`; omitting it keeps the canonical blank backdrop with the title shown, and a custom backdrop takes a background, padding (default `s`) and `showTitle` (default true). `layout` sets Width (2-6, default 6) and Height (Auto by default, a manual value is at least 50px). The block is staged in the portal's customizer draft (not published immediately). Requires portals.write access.
117
+ */
118
+ addPortalCountdownBlock(params: {
119
+ path: {
120
+ orgId: orgIdInPathRequired;
121
+ portalId: globalIdInPathRequired;
122
+ pageId: globalIdInPathRequired;
123
+ };
124
+ headers?: Record<string, string>;
125
+ body: AddPortalCountdownBlockRequestContract;
126
+ }): Promise<AddPortalCountdownBlockResponseContract>;
127
+ /**
128
+ * Add a Database block to a portal page
129
+ * Stages one Customizer-compatible Database block on an EXISTING portal page — the programmatic equivalent of the customizer's "Database" tile. It creates exactly one flexible block with a single dashboard brick; no page, sidebar item, database, dashboard or view is created and the selected view's own settings are untouched. Both Customizer types are supported: `database` (Database -> Table -> View) and `dashboard` (a shared source such as All forms -> View). Pass exact ids from listPortalDatabaseBlockSources; names, aliases and URLs are rejected, and the dashboard must belong to `databaseId` in database mode. Optional `title` (default "Database"), `itemsPerPage` (10/20/50/100/200/500, default 100), `appearance` and `layout`. To change whether the view is editable call setDashboardViewReadonly separately — that is a global view setting. The block is staged in the portal's customizer draft (not published immediately). Requires portals.write access.
130
+ */
131
+ addPortalDatabaseBlock(params: {
132
+ path: {
133
+ orgId: orgIdInPathRequired;
134
+ portalId: globalIdInPathRequired;
135
+ pageId: globalIdInPathRequired;
136
+ };
137
+ headers?: Record<string, string>;
138
+ body: AddPortalDatabaseBlockRequestContract;
139
+ }): Promise<AddPortalDatabaseBlockResponseContract>;
75
140
  /**
76
141
  * Add an Embeds & Integrations block to a portal page
77
142
  * Stages one Customizer-compatible Embed block on an EXISTING portal page — the programmatic equivalent of the customizer's "Embeds & Integrations" action. No new page and no sidebar menu item is created. embedType is one of the 11 chooser variants (custom, youtube, google-drive, ms-doc, calendly, hubspot, airtable, loom, data-studio, figma, miro). For `custom` pass `content` (URL or embed code) and NOT `url`; for every named variant pass `url` and NOT `content` — the service builds the canonical iframe. hubspot here is an iframe Embed block, not a Flexible Block integration brick. For a published page resolve pageId from listPortalContent; for a page created earlier in the active draft use the pageId that operation returned. The block is staged in the portal's customizer draft (not published immediately). Returns the block id and the draft branch/seqs. Requires portals.write access.
@@ -85,6 +150,32 @@ export declare class PortalsApi {
85
150
  headers?: Record<string, string>;
86
151
  body: AddPortalEmbedBlockRequestContract;
87
152
  }): Promise<AddPortalEmbedBlockResponseContract>;
153
+ /**
154
+ * Add a Text & Media Heading block to a portal page
155
+ * Stages one Customizer-compatible Heading block on an existing portal page — the programmatic equivalent of the customizer's Text & Media "Heading" tile. `content` carries the text settings (plain text, one palette colour token such as `cyan-700` — never HEX or CSS —, size `s`/`m`/`l`/`xl`, a unique set of `bold`, `italic`, `underline`, `lineThrough` styles and alignment). `appearance` is the Customizer Appearance section; a `custom` backdrop takes a colour, gradient or one of the five preset background images (`azure`, `mira`, `solis`, `serenity`, `glow`) — an image URL, asset id or upload is rejected. HTML, Markdown, CSS, Tailwind classes, a wrapper title and raw bricks are not accepted. Defaults: text "Your Title Goes Here", size `l`, no styles, left alignment and a blank backdrop. It creates exactly one flexible block on an EXISTING page; no page, sidebar item or media asset is created. `layout` sets Customizer Width (2-6, default 6) and Height (Auto by default, a manual value is at least 50px); `rowspan`, row placement and responsive values are not part of this contract. The block is staged in the portal's customizer draft (not published immediately). Requires portals.write access.
156
+ */
157
+ addPortalHeadingBlock(params: {
158
+ path: {
159
+ orgId: orgIdInPathRequired;
160
+ portalId: globalIdInPathRequired;
161
+ pageId: globalIdInPathRequired;
162
+ };
163
+ headers?: Record<string, string>;
164
+ body: AddPortalHeadingBlockRequestContract;
165
+ }): Promise<PortalTextAndMediaBlockResponseContract>;
166
+ /**
167
+ * Add a Text & Media Image block to a portal page
168
+ * Stages one Customizer-compatible Image block on an existing portal page — the programmatic equivalent of the customizer's Text & Media "Image" tile. It always creates the customizer's default stock image: `assetId`, `src`, a URL, base64, a file path or name, HTML and any other image input are rejected, and so are Appearance and text settings. Only `layout` applies. It creates exactly one flexible block on an EXISTING page; no page, sidebar item or media asset is created. `layout` sets Customizer Width (2-6, default 6) and Height (Auto by default, a manual value is at least 50px); `rowspan`, row placement and responsive values are not part of this contract. The block is staged in the portal's customizer draft (not published immediately). Requires portals.write access.
169
+ */
170
+ addPortalImageBlock(params: {
171
+ path: {
172
+ orgId: orgIdInPathRequired;
173
+ portalId: globalIdInPathRequired;
174
+ pageId: globalIdInPathRequired;
175
+ };
176
+ headers?: Record<string, string>;
177
+ body: AddPortalImageBlockRequestContract;
178
+ }): Promise<PortalTextAndMediaBlockResponseContract>;
88
179
  /**
89
180
  * Add an existing Fusebase note as a block to a portal page
90
181
  * Embeds an existing Fusebase note as a content block on an existing portal page (no new page or sidebar item is created). The note must already exist in the portal's workspace and be shared into the portal (e.g. created via createPortalPageWithNote). Pass pageId (the target page node id, obtained from listPortalContent) and noteId. The block is staged in the portal's customizer draft (not published immediately): the portal owner opens the customizer, reviews the pending block, and publishes it. Returns the created block id and the draft branch/seqs. Requires portals.write access.
@@ -97,6 +188,19 @@ export declare class PortalsApi {
97
188
  headers?: Record<string, string>;
98
189
  body: AddPortalNoteBlockRequestContract;
99
190
  }): Promise<AddPortalNoteBlockResponseContract>;
191
+ /**
192
+ * Add a Text & Media Simple text block to a portal page
193
+ * Stages one Customizer-compatible Simple text block on an existing portal page — the programmatic equivalent of the customizer's Text & Media "Simple text" tile. `content` carries the text settings (plain text, one palette colour token such as `cyan-700` — never HEX or CSS —, size `s`/`m`/`l`/`xl`, a unique set of `bold`, `italic`, `underline`, `lineThrough` styles and alignment). `appearance` is the Customizer Appearance section; a `custom` backdrop takes a colour, gradient or one of the five preset background images (`azure`, `mira`, `solis`, `serenity`, `glow`) — an image URL, asset id or upload is rejected. HTML, Markdown, CSS, Tailwind classes, a wrapper title and raw bricks are not accepted. Defaults: text "Your journey starts here! Add your unique message to engage your audience.", size `m`, no styles, left alignment and a blank backdrop. It creates exactly one flexible block on an EXISTING page; no page, sidebar item or media asset is created. `layout` sets Customizer Width (2-6, default 6) and Height (Auto by default, a manual value is at least 50px); `rowspan`, row placement and responsive values are not part of this contract. The block is staged in the portal's customizer draft (not published immediately). Requires portals.write access.
194
+ */
195
+ addPortalTextBlock(params: {
196
+ path: {
197
+ orgId: orgIdInPathRequired;
198
+ portalId: globalIdInPathRequired;
199
+ pageId: globalIdInPathRequired;
200
+ };
201
+ headers?: Record<string, string>;
202
+ body: AddPortalTextBlockRequestContract;
203
+ }): Promise<PortalTextAndMediaBlockResponseContract>;
100
204
  /**
101
205
  * Invite multiple users to a portal in one call
102
206
  * Invites a batch of users to a single portal in one request, replacing N sequential inviteToPortal calls. Portal discovery (listPortals/getPortal) runs once for the whole batch. Invites are processed with bounded concurrency (default 5, max 5); the rest are queued. With background=false (default) the response waits for all invites and returns aggregated per-invitation results (status='completed'). With background=true the response returns immediately (status='processing') and invites run in the background without blocking the caller. Per-invitation orgRole/isFullAccess semantics match inviteToPortal. Invarian — before calling for client invites (orgRole='client' or unspecified): ALWAYS ask the user 'Full access (all pages) or Shared only (public pages)?' and wait for their answer.
@@ -192,6 +296,22 @@ export declare class PortalsApi {
192
296
  };
193
297
  headers?: Record<string, string>;
194
298
  }): Promise<PortalDetailContract>;
299
+ /**
300
+ * Count matching blocks on a portal page (published + draft)
301
+ * Universal preflight: how many active blocks of a given type a page already carries, counted over the published portal AND its active customizer draft — so a block staged earlier in this session is included. `type` is a canonical portal block type; `templateType` is allowed only with type='flexible' and narrows by the flexible template (e.g. type='flexible' + templateType='ai-agent' for AI Agent blocks). Returns only the count — never blocks, bricks, ids or draft events. Requires portals.write access.
302
+ */
303
+ getPortalPageBlockCount(params: {
304
+ path: {
305
+ orgId: orgIdInPathRequired;
306
+ portalId: globalIdInPathRequired;
307
+ pageId: globalIdInPathRequired;
308
+ };
309
+ query?: {
310
+ type?: string;
311
+ templateType?: string;
312
+ };
313
+ headers?: Record<string, string>;
314
+ }): Promise<GetPortalPageBlockCountResponseContract>;
195
315
  /**
196
316
  * Invite a portal manager (customizer access)
197
317
  * Invites a user as a PORTAL MANAGER via a magic link. A manager has access to the portal customizer and can build, edit, and publish the portal (layout, settings, widgets, custom code); they always get full access to all portal pages. This is a dedicated shortcut for inviteToPortal with orgRole='manager' — no access question is needed (managers are always full access). Returns a magic link for direct portal/customizer access without email confirmation. Requires portals.manage access.
@@ -216,6 +336,21 @@ export declare class PortalsApi {
216
336
  headers?: Record<string, string>;
217
337
  body: InviteToPortalRequestContract;
218
338
  }): Promise<InviteToPortalResponseContract>;
339
+ /**
340
+ * Search or browse the AI agents available to the caller
341
+ * Searches the organization's AI agents (the caller's own org agents plus the available default agents) by title so an AI Agent block can target one by exact id. ALWAYS call this before addPortalAiAgentBlock — never guess or invent an agent id. `query` is optional: omit it to browse the first bounded page. Returns a single page of { id, title, description?, iconName?, iconColor? } and an opaque nextCursor when more pages exist. Show one page at a time and ask before fetching the next; never aggregate the full agent list. Requires portals.write access.
342
+ */
343
+ listPortalAiAgents(params: {
344
+ path: {
345
+ orgId: orgIdInPathRequired;
346
+ };
347
+ query?: {
348
+ query?: string;
349
+ limit?: number;
350
+ cursor?: string;
351
+ };
352
+ headers?: Record<string, string>;
353
+ }): Promise<ListPortalAiAgentsResponseContract>;
219
354
  /**
220
355
  * List a portal's chat channels for the Chat block picker
221
356
  * Lists the real, listable chat channels of a portal so a Chat block can target one by exact id. DMs, group DMs and hidden channels are excluded; the default channel is returned first. ALWAYS call this before addPortalChatBlock with a channel target — never guess a channel id and never assume `general` exists. This is the Chat widget's channel list, distinct from the portal's system chat menu item and the chats-dashboard block. Requires portals.write access.
@@ -254,6 +389,23 @@ export declare class PortalsApi {
254
389
  };
255
390
  headers?: Record<string, string>;
256
391
  }): Promise<ListPortalContentResponseContract>;
392
+ /**
393
+ * Discover Database block sources
394
+ * Read-only discovery of the exact Database/Dashboard/View ids that addPortalDatabaseBlock requires. `type=database` without `databaseId` returns ONE page of databases (`databases`, `page`, `limit` 20, `total`, optional `nextPage`); `query` searches Database title and alias case-insensitively. `type=database` with `databaseId` returns that database and every Table with its Views. `type=dashboard` returns all shared Dashboard sources with their Views, unpaged. The response is a compact projection: ids, titles, aliases and isDefault only — never schema, filters, representations, metadata, scopes or row data. Requires portals.write access.
395
+ */
396
+ listPortalDatabaseBlockSources(params: {
397
+ path: {
398
+ orgId: orgIdInPathRequired;
399
+ };
400
+ query?: {
401
+ type?: string;
402
+ query?: string;
403
+ page?: number;
404
+ limit?: number;
405
+ databaseId?: string;
406
+ };
407
+ headers?: Record<string, string>;
408
+ }): Promise<ListPortalDatabaseBlockSourcesResponseContract>;
257
409
  /**
258
410
  * List organization portals
259
411
  * Returns portals visible for the caller in the organization. Requires portals.read and org access.
@@ -275,6 +427,19 @@ export declare class PortalsApi {
275
427
  };
276
428
  headers?: Record<string, string>;
277
429
  }): Promise<PublishPortalDraftResponseContract>;
430
+ /**
431
+ * Restrict or allow editing of a dashboard view
432
+ * The customizer's "Restrict editing" switch. This is a GLOBAL view setting, not a portal-block setting: it applies everywhere the view is used, including other portal blocks and the dashboard itself. Call it only when the user explicitly asks to restrict or allow editing; it is never part of addPortalDatabaseBlock. Requires dashboard.write access.
433
+ */
434
+ setDashboardViewReadonly(params: {
435
+ path: {
436
+ orgId: orgIdInPathRequired;
437
+ dashboardId: string;
438
+ viewId: string;
439
+ };
440
+ headers?: Record<string, string>;
441
+ body: SetDashboardViewReadonlyRequestContract;
442
+ }): Promise<SetDashboardViewReadonlyResponseContract>;
278
443
  /**
279
444
  * Update portal access mode
280
445
  * Sets the portal access mode: 'open' (anyone), 'invite-only' (invited users only), 'email' (visitor enters an email, no verification), or 'email-verified' (email with confirmation). The change is staged in the portal's customizer draft (not published immediately): the portal owner opens the customizer, reviews the pending change, and publishes it. Returns the staged access mode and the draft branch/seq. Requires portals.write access.
@@ -11,6 +11,21 @@ class PortalsApi {
11
11
  constructor(client) {
12
12
  this.client = client;
13
13
  }
14
+ /**
15
+ * Add an AI Agent block to a portal page
16
+ * Stages one Customizer-compatible AI Agent block on an EXISTING portal page — the programmatic equivalent of the customizer's "AI Agent" tile (a flexible block with one ai-agent brick). No new page and no sidebar menu item is created. Pass only agentId, the exact id from listPortalAiAgents; the block title is the agent's current title and every layout/brick detail is fixed by the service. Immediately before calling this, check getPortalPageBlockCount with type='flexible' and templateType='ai-agent': only ONE AI Agent block is allowed per page and a second returns 400. For a published page resolve pageId from listPortalContent; for a page created earlier in the active draft use the pageId that operation returned. The block is staged in the portal's customizer draft (not published immediately). Returns the block id and the draft branch/seqs. Requires portals.write access.
17
+ */
18
+ async addPortalAiAgentBlock(params) {
19
+ return this.client.request({
20
+ method: "POST",
21
+ path: "/:orgId/portals/:portalId/pages/:pageId/blocks/ai-agent",
22
+ pathParams: params.path,
23
+ headers: params.headers,
24
+ body: params.body,
25
+ opId: "addPortalAiAgentBlock",
26
+ expectedContentType: "application/json",
27
+ });
28
+ }
14
29
  /**
15
30
  * Add a published app as a block on an existing portal page
16
31
  * Stages one published Fusebase app as a flexible app-feature block on an EXISTING portal page. No new page and no sidebar menu item is created — use addPortalAppPage when the app should get its own sidebar page. Pass productId (the product that owns the app) and appId (the app to embed); resolve both, plus productType and productOrgId, with findPublishedApps. For a managed product (Customizer "Managed Products") also pass productType='managed' and productOrgId. For a published page resolve pageId from listPortalContent; for a page created earlier in the active draft use the pageId that operation returned. The block is staged in the portal's customizer draft (not published immediately). Returns the block id, the page the block was staged on, and the draft branch/seqs. Requires portals.write access.
@@ -58,7 +73,7 @@ class PortalsApi {
58
73
  }
59
74
  /**
60
75
  * Add a block of any palette type to a portal page
61
- * Stages a single block of any supported type onto an existing portal page — the universal building block behind the customizer's 'Add new block' palette (no new page or sidebar item is created). Pass pageId (the target page node id from listPortalContent) and type. Supported types: note, content, info, docs, help, request, meetings, links, task-list, projection, files-dashboard, tasks-dashboard, chats-dashboard, files-recent, files-bucket, flexible. Type-specific fields: note/content require noteId; flexible requires template (e.g. {type:'text'|'image'|'title'|'code'|'form'|'dashboard'|'ai-agent'|'app-feature'|...}) and may carry bricks; info/projection/task-list and others take their fields via the free-form `properties` object (e.g. image/link, sourcePortalId/sourcePageId/sourceBlockId, taskListIds). This op does NOT accept type='embed' or type='chat' — use addPortalEmbedBlock for Embed blocks and addPortalChatBlock for Chat blocks. Use addPortalNoteBlock for the common note case or addPortalAppPage for an app on its own page. Note: a `content` block renames the page to its title, so leave title empty for content blocks. The block is staged in the portal's customizer draft (not published immediately); the owner reviews and publishes it. Returns the block id and the draft branch/seqs. Requires portals.write access.
76
+ * Stages a single block of any supported type onto an existing portal page — the universal building block behind the customizer's 'Add new block' palette (no new page or sidebar item is created). Pass pageId (the target page node id from listPortalContent) and type. Supported types: note, content, info, docs, help, request, meetings, links, task-list, projection, files-dashboard, tasks-dashboard, chats-dashboard, files-recent, files-bucket, flexible. Type-specific fields: note/content require noteId; flexible requires template (e.g. {type:'text'|'image'|'title'|'code'|'form'|'dashboard'|'app-feature'|...}) and may carry bricks; info/projection/task-list and others take their fields via the free-form `properties` object (e.g. image/link, sourcePortalId/sourcePageId/sourceBlockId, taskListIds). This op does NOT accept type='embed', a flexible block with template.type='dashboard' or a dashboard brick (use addPortalDatabaseBlock) or type='chat' — use addPortalEmbedBlock for Embed blocks and addPortalChatBlock for Chat blocks — and it does NOT accept a flexible ai-agent template or an ai-agent brick: use addPortalAiAgentBlock, which binds the agent to the caller. Use addPortalNoteBlock for the common note case or addPortalAppPage for an app on its own page. Note: a `content` block renames the page to its title, so leave title empty for content blocks. The block is staged in the portal's customizer draft (not published immediately); the owner reviews and publishes it. Returns the block id and the draft branch/seqs. Requires portals.write access.
62
77
  */
63
78
  async addPortalBlock(params) {
64
79
  return this.client.request({
@@ -71,6 +86,36 @@ class PortalsApi {
71
86
  expectedContentType: "application/json",
72
87
  });
73
88
  }
89
+ /**
90
+ * Add a Card block to a portal page
91
+ * Stages one Customizer-compatible Card on an EXISTING portal page — the programmatic equivalent of the customizer's Content display "Card" tile. It creates exactly one flexible block with the five canonical bricks (Image, Heading, Description, Button, Destination URL); no page, sidebar item or media asset is created. `view` is the Card Type: `top-image`, `left-image`, `right-image` or `fill-image` (default `top-image`; `fill-image` defaults the text to white). `content` configures the bricks: `image.visible` only — the Card always uses the built-in template image and an `src`/URL/asset id/upload is rejected —, `heading` and `description` (plain text plus one palette colour token such as `cyan-700`, size `s`/`m`/`l`/`xl`, a unique set of `bold`/`italic`/`underline`/`lineThrough` styles and alignment), `button` (plain label sent as `button.text` — there is no `label` field and sending one is rejected — with no dynamic variables) and `destination`. `visible` defaults to `true`, so a visible item does NOT need `visible: true`: send `content.button: {text: "Open"}` to set an enabled Button label. Any of Image, Heading, Description and Button can be hidden with `visible: false`, which then must be the item's only field. `destination` is shared by the whole Card and its Button: an exact `pageId` of a page in THIS portal, an absolute https URL, an email address, or `null` for no link — a raw DynamicLink, `javascript:`/`data:` URL or caller-supplied internal title/targetId is rejected, and the link target (new tab) is not configurable. `appearance` is optional; omitting it keeps the Card's canonical bare wrapper, and a `custom` backdrop takes a colour, gradient or one of the five preset background images (`azure`, `mira`, `solis`, `serenity`, `glow`). `layout` sets Customizer Width (2-6, default 3) and Height (Auto by default, a manual value is at least 50px). HTML, Markdown, CSS, Tailwind classes, a wrapper title and raw bricks are not accepted. The block is staged in the portal's customizer draft (not published immediately). Requires portals.write access.
92
+ */
93
+ async addPortalCardBlock(params) {
94
+ return this.client.request({
95
+ method: "POST",
96
+ path: "/:orgId/portals/:portalId/pages/:pageId/blocks/card",
97
+ pathParams: params.path,
98
+ headers: params.headers,
99
+ body: params.body,
100
+ opId: "addPortalCardBlock",
101
+ expectedContentType: "application/json",
102
+ });
103
+ }
104
+ /**
105
+ * Add a Carousel block to a portal page
106
+ * Stages one Customizer-compatible Carousel on an EXISTING portal page — the programmatic equivalent of the customizer's Content display "Carousel" tile. It creates exactly one flexible block with a single Carousel brick; no page, sidebar item or media asset is created. Omit `content` to get the Customizer default of three slides (Deliberation, Elaboration, Presentation) with their built-in images, descriptions, More buttons and links. `content.items` replaces that list entirely and must hold 1 to 6 slides in visual order; the slide index is taken from the array position and is not accepted from the caller. Each slide takes `caption` and `description` (plain text; only `description` supports the `{{ClientName}}` and `{{ClientLastName}}` variables), `button: {text}` or `null` for no Button, and `destination` or `null` for no link — an exact `pageId` of a page in THIS portal, an absolute https URL or an email address. The slide surface and its Button share that one destination. Every slide image is a built-in one: an image/video URL, asset id, file name, base64, local path or upload is rejected, as are a raw DynamicLink, raw item index, brick, CSS class, autoplay, duration, controls and indicators. Carousel has no public Appearance settings. `layout` sets Customizer Width (2-6, default 6) and Height (Auto by default, a manual value is at least 50px). The block is staged in the portal's customizer draft (not published immediately). Requires portals.write access.
107
+ */
108
+ async addPortalCarouselBlock(params) {
109
+ return this.client.request({
110
+ method: "POST",
111
+ path: "/:orgId/portals/:portalId/pages/:pageId/blocks/carousel",
112
+ pathParams: params.path,
113
+ headers: params.headers,
114
+ body: params.body,
115
+ opId: "addPortalCarouselBlock",
116
+ expectedContentType: "application/json",
117
+ });
118
+ }
74
119
  /**
75
120
  * Add a Chat block to a portal page
76
121
  * Stages one Customizer-compatible Chat block on an EXISTING portal page — the programmatic equivalent of the customizer's "Chat" action. Pass exactly one target: { type: 'channel', channelId } (id from listPortalChatChannels) or { type: 'dm', userId } (an active org member's userId). membersOnly is channel-only (default true; a private channel requires true; forbidden for dm). One active Chat block is allowed per page — a second returns 409. Creates one chat widget configuration and stages the block in the customizer draft (not published immediately). This is a Chat WIDGET on a page, distinct from the portal's system chat menu item and the chats-dashboard block. For a published page resolve pageId from listPortalContent; for a page created earlier in the active draft use the pageId that operation returned. Returns the block id and the draft branch/seqs. Requires portals.write access.
@@ -86,6 +131,36 @@ class PortalsApi {
86
131
  expectedContentType: "application/json",
87
132
  });
88
133
  }
134
+ /**
135
+ * Add a Countdown block to a portal page
136
+ * Stages one Customizer-compatible Countdown on an EXISTING portal page — the programmatic equivalent of the customizer's Content display "Countdown" tile. It creates exactly one flexible block with a single Countdown item that ticks down days, hours, minutes and seconds to a future moment; no page, sidebar item or external entity is created. The body may be empty, which reproduces the Customizer default: the title "Countdown" and a target 30 days after creation. `content.targetAt` is an absolute RFC 3339 date-time with `Z` or an explicit UTC offset — epoch seconds/milliseconds, a timezone-less local date and a duration are rejected, as are a raw timestamp, brick, renderer style, the item's internal title and its fixed days/hours/min/sec labels. The target must not be in the past or more than 99 days after creation. `title` is the block title (plain text, only the `{{ClientName}}` and `{{ClientLastName}}` variables). `appearance` sets Customizer Backdrop `none`, `blank` or `custom`; omitting it keeps the canonical blank backdrop with the title shown, and a custom backdrop takes a background, padding (default `s`) and `showTitle` (default true). `layout` sets Width (2-6, default 6) and Height (Auto by default, a manual value is at least 50px). The block is staged in the portal's customizer draft (not published immediately). Requires portals.write access.
137
+ */
138
+ async addPortalCountdownBlock(params) {
139
+ return this.client.request({
140
+ method: "POST",
141
+ path: "/:orgId/portals/:portalId/pages/:pageId/blocks/countdown",
142
+ pathParams: params.path,
143
+ headers: params.headers,
144
+ body: params.body,
145
+ opId: "addPortalCountdownBlock",
146
+ expectedContentType: "application/json",
147
+ });
148
+ }
149
+ /**
150
+ * Add a Database block to a portal page
151
+ * Stages one Customizer-compatible Database block on an EXISTING portal page — the programmatic equivalent of the customizer's "Database" tile. It creates exactly one flexible block with a single dashboard brick; no page, sidebar item, database, dashboard or view is created and the selected view's own settings are untouched. Both Customizer types are supported: `database` (Database -> Table -> View) and `dashboard` (a shared source such as All forms -> View). Pass exact ids from listPortalDatabaseBlockSources; names, aliases and URLs are rejected, and the dashboard must belong to `databaseId` in database mode. Optional `title` (default "Database"), `itemsPerPage` (10/20/50/100/200/500, default 100), `appearance` and `layout`. To change whether the view is editable call setDashboardViewReadonly separately — that is a global view setting. The block is staged in the portal's customizer draft (not published immediately). Requires portals.write access.
152
+ */
153
+ async addPortalDatabaseBlock(params) {
154
+ return this.client.request({
155
+ method: "POST",
156
+ path: "/:orgId/portals/:portalId/pages/:pageId/blocks/database",
157
+ pathParams: params.path,
158
+ headers: params.headers,
159
+ body: params.body,
160
+ opId: "addPortalDatabaseBlock",
161
+ expectedContentType: "application/json",
162
+ });
163
+ }
89
164
  /**
90
165
  * Add an Embeds & Integrations block to a portal page
91
166
  * Stages one Customizer-compatible Embed block on an EXISTING portal page — the programmatic equivalent of the customizer's "Embeds & Integrations" action. No new page and no sidebar menu item is created. embedType is one of the 11 chooser variants (custom, youtube, google-drive, ms-doc, calendly, hubspot, airtable, loom, data-studio, figma, miro). For `custom` pass `content` (URL or embed code) and NOT `url`; for every named variant pass `url` and NOT `content` — the service builds the canonical iframe. hubspot here is an iframe Embed block, not a Flexible Block integration brick. For a published page resolve pageId from listPortalContent; for a page created earlier in the active draft use the pageId that operation returned. The block is staged in the portal's customizer draft (not published immediately). Returns the block id and the draft branch/seqs. Requires portals.write access.
@@ -101,6 +176,36 @@ class PortalsApi {
101
176
  expectedContentType: "application/json",
102
177
  });
103
178
  }
179
+ /**
180
+ * Add a Text & Media Heading block to a portal page
181
+ * Stages one Customizer-compatible Heading block on an existing portal page — the programmatic equivalent of the customizer's Text & Media "Heading" tile. `content` carries the text settings (plain text, one palette colour token such as `cyan-700` — never HEX or CSS —, size `s`/`m`/`l`/`xl`, a unique set of `bold`, `italic`, `underline`, `lineThrough` styles and alignment). `appearance` is the Customizer Appearance section; a `custom` backdrop takes a colour, gradient or one of the five preset background images (`azure`, `mira`, `solis`, `serenity`, `glow`) — an image URL, asset id or upload is rejected. HTML, Markdown, CSS, Tailwind classes, a wrapper title and raw bricks are not accepted. Defaults: text "Your Title Goes Here", size `l`, no styles, left alignment and a blank backdrop. It creates exactly one flexible block on an EXISTING page; no page, sidebar item or media asset is created. `layout` sets Customizer Width (2-6, default 6) and Height (Auto by default, a manual value is at least 50px); `rowspan`, row placement and responsive values are not part of this contract. The block is staged in the portal's customizer draft (not published immediately). Requires portals.write access.
182
+ */
183
+ async addPortalHeadingBlock(params) {
184
+ return this.client.request({
185
+ method: "POST",
186
+ path: "/:orgId/portals/:portalId/pages/:pageId/blocks/heading",
187
+ pathParams: params.path,
188
+ headers: params.headers,
189
+ body: params.body,
190
+ opId: "addPortalHeadingBlock",
191
+ expectedContentType: "application/json",
192
+ });
193
+ }
194
+ /**
195
+ * Add a Text & Media Image block to a portal page
196
+ * Stages one Customizer-compatible Image block on an existing portal page — the programmatic equivalent of the customizer's Text & Media "Image" tile. It always creates the customizer's default stock image: `assetId`, `src`, a URL, base64, a file path or name, HTML and any other image input are rejected, and so are Appearance and text settings. Only `layout` applies. It creates exactly one flexible block on an EXISTING page; no page, sidebar item or media asset is created. `layout` sets Customizer Width (2-6, default 6) and Height (Auto by default, a manual value is at least 50px); `rowspan`, row placement and responsive values are not part of this contract. The block is staged in the portal's customizer draft (not published immediately). Requires portals.write access.
197
+ */
198
+ async addPortalImageBlock(params) {
199
+ return this.client.request({
200
+ method: "POST",
201
+ path: "/:orgId/portals/:portalId/pages/:pageId/blocks/image",
202
+ pathParams: params.path,
203
+ headers: params.headers,
204
+ body: params.body,
205
+ opId: "addPortalImageBlock",
206
+ expectedContentType: "application/json",
207
+ });
208
+ }
104
209
  /**
105
210
  * Add an existing Fusebase note as a block to a portal page
106
211
  * Embeds an existing Fusebase note as a content block on an existing portal page (no new page or sidebar item is created). The note must already exist in the portal's workspace and be shared into the portal (e.g. created via createPortalPageWithNote). Pass pageId (the target page node id, obtained from listPortalContent) and noteId. The block is staged in the portal's customizer draft (not published immediately): the portal owner opens the customizer, reviews the pending block, and publishes it. Returns the created block id and the draft branch/seqs. Requires portals.write access.
@@ -116,6 +221,21 @@ class PortalsApi {
116
221
  expectedContentType: "application/json",
117
222
  });
118
223
  }
224
+ /**
225
+ * Add a Text & Media Simple text block to a portal page
226
+ * Stages one Customizer-compatible Simple text block on an existing portal page — the programmatic equivalent of the customizer's Text & Media "Simple text" tile. `content` carries the text settings (plain text, one palette colour token such as `cyan-700` — never HEX or CSS —, size `s`/`m`/`l`/`xl`, a unique set of `bold`, `italic`, `underline`, `lineThrough` styles and alignment). `appearance` is the Customizer Appearance section; a `custom` backdrop takes a colour, gradient or one of the five preset background images (`azure`, `mira`, `solis`, `serenity`, `glow`) — an image URL, asset id or upload is rejected. HTML, Markdown, CSS, Tailwind classes, a wrapper title and raw bricks are not accepted. Defaults: text "Your journey starts here! Add your unique message to engage your audience.", size `m`, no styles, left alignment and a blank backdrop. It creates exactly one flexible block on an EXISTING page; no page, sidebar item or media asset is created. `layout` sets Customizer Width (2-6, default 6) and Height (Auto by default, a manual value is at least 50px); `rowspan`, row placement and responsive values are not part of this contract. The block is staged in the portal's customizer draft (not published immediately). Requires portals.write access.
227
+ */
228
+ async addPortalTextBlock(params) {
229
+ return this.client.request({
230
+ method: "POST",
231
+ path: "/:orgId/portals/:portalId/pages/:pageId/blocks/text",
232
+ pathParams: params.path,
233
+ headers: params.headers,
234
+ body: params.body,
235
+ opId: "addPortalTextBlock",
236
+ expectedContentType: "application/json",
237
+ });
238
+ }
119
239
  /**
120
240
  * Invite multiple users to a portal in one call
121
241
  * Invites a batch of users to a single portal in one request, replacing N sequential inviteToPortal calls. Portal discovery (listPortals/getPortal) runs once for the whole batch. Invites are processed with bounded concurrency (default 5, max 5); the rest are queued. With background=false (default) the response waits for all invites and returns aggregated per-invitation results (status='completed'). With background=true the response returns immediately (status='processing') and invites run in the background without blocking the caller. Per-invitation orgRole/isFullAccess semantics match inviteToPortal. Invarian — before calling for client invites (orgRole='client' or unspecified): ALWAYS ask the user 'Full access (all pages) or Shared only (public pages)?' and wait for their answer.
@@ -235,6 +355,21 @@ class PortalsApi {
235
355
  expectedContentType: "application/json",
236
356
  });
237
357
  }
358
+ /**
359
+ * Count matching blocks on a portal page (published + draft)
360
+ * Universal preflight: how many active blocks of a given type a page already carries, counted over the published portal AND its active customizer draft — so a block staged earlier in this session is included. `type` is a canonical portal block type; `templateType` is allowed only with type='flexible' and narrows by the flexible template (e.g. type='flexible' + templateType='ai-agent' for AI Agent blocks). Returns only the count — never blocks, bricks, ids or draft events. Requires portals.write access.
361
+ */
362
+ async getPortalPageBlockCount(params) {
363
+ return this.client.request({
364
+ method: "GET",
365
+ path: "/:orgId/portals/:portalId/pages/:pageId/blocks/count",
366
+ pathParams: params.path,
367
+ query: params.query,
368
+ headers: params.headers,
369
+ opId: "getPortalPageBlockCount",
370
+ expectedContentType: "application/json",
371
+ });
372
+ }
238
373
  /**
239
374
  * Invite a portal manager (customizer access)
240
375
  * Invites a user as a PORTAL MANAGER via a magic link. A manager has access to the portal customizer and can build, edit, and publish the portal (layout, settings, widgets, custom code); they always get full access to all portal pages. This is a dedicated shortcut for inviteToPortal with orgRole='manager' — no access question is needed (managers are always full access). Returns a magic link for direct portal/customizer access without email confirmation. Requires portals.manage access.
@@ -265,6 +400,21 @@ class PortalsApi {
265
400
  expectedContentType: "application/json",
266
401
  });
267
402
  }
403
+ /**
404
+ * Search or browse the AI agents available to the caller
405
+ * Searches the organization's AI agents (the caller's own org agents plus the available default agents) by title so an AI Agent block can target one by exact id. ALWAYS call this before addPortalAiAgentBlock — never guess or invent an agent id. `query` is optional: omit it to browse the first bounded page. Returns a single page of { id, title, description?, iconName?, iconColor? } and an opaque nextCursor when more pages exist. Show one page at a time and ask before fetching the next; never aggregate the full agent list. Requires portals.write access.
406
+ */
407
+ async listPortalAiAgents(params) {
408
+ return this.client.request({
409
+ method: "GET",
410
+ path: "/:orgId/ai-agents",
411
+ pathParams: params.path,
412
+ query: params.query,
413
+ headers: params.headers,
414
+ opId: "listPortalAiAgents",
415
+ expectedContentType: "application/json",
416
+ });
417
+ }
268
418
  /**
269
419
  * List a portal's chat channels for the Chat block picker
270
420
  * Lists the real, listable chat channels of a portal so a Chat block can target one by exact id. DMs, group DMs and hidden channels are excluded; the default channel is returned first. ALWAYS call this before addPortalChatBlock with a channel target — never guess a channel id and never assume `general` exists. This is the Chat widget's channel list, distinct from the portal's system chat menu item and the chats-dashboard block. Requires portals.write access.
@@ -308,6 +458,21 @@ class PortalsApi {
308
458
  expectedContentType: "application/json",
309
459
  });
310
460
  }
461
+ /**
462
+ * Discover Database block sources
463
+ * Read-only discovery of the exact Database/Dashboard/View ids that addPortalDatabaseBlock requires. `type=database` without `databaseId` returns ONE page of databases (`databases`, `page`, `limit` 20, `total`, optional `nextPage`); `query` searches Database title and alias case-insensitively. `type=database` with `databaseId` returns that database and every Table with its Views. `type=dashboard` returns all shared Dashboard sources with their Views, unpaged. The response is a compact projection: ids, titles, aliases and isDefault only — never schema, filters, representations, metadata, scopes or row data. Requires portals.write access.
464
+ */
465
+ async listPortalDatabaseBlockSources(params) {
466
+ return this.client.request({
467
+ method: "GET",
468
+ path: "/:orgId/database-block-sources",
469
+ pathParams: params.path,
470
+ query: params.query,
471
+ headers: params.headers,
472
+ opId: "listPortalDatabaseBlockSources",
473
+ expectedContentType: "application/json",
474
+ });
475
+ }
311
476
  /**
312
477
  * List organization portals
313
478
  * Returns portals visible for the caller in the organization. Requires portals.read and org access.
@@ -336,6 +501,21 @@ class PortalsApi {
336
501
  expectedContentType: "application/json",
337
502
  });
338
503
  }
504
+ /**
505
+ * Restrict or allow editing of a dashboard view
506
+ * The customizer's "Restrict editing" switch. This is a GLOBAL view setting, not a portal-block setting: it applies everywhere the view is used, including other portal blocks and the dashboard itself. Call it only when the user explicitly asks to restrict or allow editing; it is never part of addPortalDatabaseBlock. Requires dashboard.write access.
507
+ */
508
+ async setDashboardViewReadonly(params) {
509
+ return this.client.request({
510
+ method: "PUT",
511
+ path: "/:orgId/dashboards/:dashboardId/views/:viewId/readonly",
512
+ pathParams: params.path,
513
+ headers: params.headers,
514
+ body: params.body,
515
+ opId: "setDashboardViewReadonly",
516
+ expectedContentType: "application/json",
517
+ });
518
+ }
339
519
  /**
340
520
  * Update portal access mode
341
521
  * Sets the portal access mode: 'open' (anyone), 'invite-only' (invited users only), 'email' (visitor enters an email, no verification), or 'email-verified' (email with confirmation). The change is staged in the portal's customizer draft (not published immediately): the portal owner opens the customizer, reviews the pending change, and publishes it. Returns the staged access mode and the draft branch/seq. Requires portals.write access.
@@ -128,6 +128,13 @@ export interface FusebaseAuthPasswordRestoreRequestContract {
128
128
  export interface FusebaseAuthPasswordRestoreResponseContract {
129
129
  ok: true;
130
130
  }
131
+ export interface FusebaseAuthSetInitialPasswordRequestContract {
132
+ password: string;
133
+ }
134
+ export interface FusebaseAuthSetInitialPasswordResponseContract {
135
+ ok: true;
136
+ userId: number;
137
+ }
131
138
  export interface FusebaseAuthRestoreKeyRequestContract {
132
139
  /**
133
140
  * User email whose password-restore key to mint.