From b4585c0522c04dbfad36e2f9d975d1b24c4297b0 Mon Sep 17 00:00:00 2001 From: "Sam (automated drift fix)" Date: Wed, 29 Apr 2026 14:00:39 +0300 Subject: [PATCH 1/4] docs(connectors): clarify app-user tokens and module overview - Describe app-scoped vs end-user connections and link getConnection vs getCurrentAppUserConnection - Document on-behalf-of / createClientFromRequest context for per-user token calls - Cross-link UserConnectorsModule for browser OAuth flows - Expand getCurrentAppUserConnection JSDoc (vs deprecated string token, second example for connectionConfig) Made-with: Cursor --- src/modules/connectors.types.ts | 39 ++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/modules/connectors.types.ts b/src/modules/connectors.types.ts index 9d79edc..de4e863 100644 --- a/src/modules/connectors.types.ts +++ b/src/modules/connectors.types.ts @@ -49,9 +49,16 @@ export interface AppUserConnectorConnectionResponse { } /** - * Connectors module for managing app-scoped OAuth tokens for external services. + * Connectors module for managing OAuth tokens for external services. * - * This module allows you to retrieve OAuth access tokens for external services that the app has connected to. Connectors are app-scoped. When an app builder connects an integration like Google Calendar, Slack, or GitHub, all users of the app share that same connection. + * Use this module in **service role** mode (`base44.asServiceRole.connectors`) from server-side code. + * + * There are two ways to obtain tokens: + * + * - **App-scoped connections** — The app builder connects an integration once; every user of the app shares that OAuth token. Call {@link getConnection} with an [integration type](#available-connectors) string (for example `'googlecalendar'` or `'slack'`). + * - **End-user (app-user) connections** — Each signed-in end user has their own OAuth token for connectors that support per-user auth. Call {@link getCurrentAppUserConnection} with the **connector ID** (the org connector's database ID), not the integration type. The API returns tokens for the user your request acts on behalf of: when the client is created with both a service token and the end user's JWT (for example via {@link createClientFromRequest | createClientFromRequest()} in a Base44 backend function), requests include the `on-behalf-of` header so the correct user's connection is resolved. + * + * End users start or revoke OAuth from the browser using {@link UserConnectorsModule | `base44.connectors`} (`connectAppUser` / `disconnectAppUser`). * * Unlike the integrations module that provides pre-built functions, connectors give you * raw OAuth tokens so you can call external service APIs directly with full control over @@ -60,7 +67,7 @@ export interface AppUserConnectorConnectionResponse { * * ## Available connectors * - * All connectors work through [`getConnection()`](#getconnection). Pass the integration type string and use the returned OAuth token to call the external service's API directly. + * For **app-scoped** tokens, pass the integration type string to {@link getConnection}. Use the returned `accessToken` (and `connectionConfig` when the connector provides extra parameters) to call the external service's API directly. * * | Service | Type identifier | * |---|---| @@ -108,7 +115,7 @@ export interface AppUserConnectorConnectionResponse { * * ## Dynamic Types * - * If you're working in a TypeScript project, you can generate types from your app's connector configurations to get autocomplete on integration type names when calling `getConnection()`. See the [Dynamic Types](/developers/references/sdk/getting-started/dynamic-types) guide to get started. + * If you're working in a TypeScript project, you can generate types from your app's connector configurations to get autocomplete on integration type names when calling {@link getConnection}. See the [Dynamic Types](/developers/references/sdk/getting-started/dynamic-types) guide to get started. */ export interface ConnectorsModule { /** @@ -267,13 +274,13 @@ export interface ConnectorsModule { getCurrentAppUserAccessToken(connectorId: string): Promise; /** - * Retrieves the OAuth access token and connection configuration for an end user's - * connection to a specific connector. + * Retrieves the OAuth access token and connection configuration for an end user's connection to a specific connector. * - * Returns both the OAuth token and any connection-specific configuration that - * belongs to the currently authenticated end user for the specified connector. + * Use this instead of {@link getCurrentAppUserAccessToken} when you need `connectionConfig` (for example a subdomain or other parameters the integration requires for API URLs). * - * @param connectorId - The connector ID (OrgConnector database ID). + * The token belongs to the **end user the request acts on behalf of**. In practice, call from server-side code where the client was created with a service token **and** the end user's JWT so the runtime forwards an `on-behalf-of` header (for example {@link createClientFromRequest | createClientFromRequest()} in a Base44 backend function). + * + * @param connectorId - The connector ID (OrgConnector database ID), not the integration type string. * @returns Promise resolving to an {@link AppUserConnectorConnectionResponse} with `accessToken` and `connectionConfig`. * * @example @@ -282,9 +289,21 @@ export interface ConnectorsModule { * const { accessToken, connectionConfig } = await base44.asServiceRole.connectors.getCurrentAppUserConnection('abc123def'); * * const response = await fetch('https://www.googleapis.com/calendar/v3/calendars/primary/events', { - * headers: { 'Authorization': `Bearer ${accessToken}` } + * headers: { Authorization: `Bearer ${accessToken}` } * }); * ``` + * + * @example + * ```typescript + * // Using connectionConfig for APIs that need extra connection parameters + * const { accessToken, connectionConfig } = await base44.asServiceRole.connectors.getCurrentAppUserConnection('abc123def'); + * + * const subdomain = connectionConfig?.subdomain; + * const data = await fetch( + * `https://${subdomain}.example.com/api/v1/resources`, + * { headers: { Authorization: `Bearer ${accessToken}` } } + * ).then((r) => r.json()); + * ``` */ getCurrentAppUserConnection(connectorId: string): Promise; } From 6afe18aa12deade850fc3654791aac74b3e4e502 Mon Sep 17 00:00:00 2001 From: "Sam (automated drift fix)" Date: Mon, 4 May 2026 14:56:53 +0300 Subject: [PATCH 2/4] docs(connectors): overhaul ConnectorsModule docs with shared and app user connector flows - Restructure module intro with ## Shared connectors and ## App user connectors sections - Merge UserConnectorsModule (connectAppUser, disconnectAppUser) into ConnectorsModule page via post-processing pipeline - Add connectionConfig docs and expanded examples to getConnection and getCurrentAppUserConnection - Add Available connectors table with all supported integration types - Mark getCurrentAppUserAccessToken as @internal - Standardise example response handling across all methods --- .../appended-articles.json | 3 +- .../file-processing/file-processing.js | 38 ++++- .../types-to-delete-after-processing.json | 3 +- src/modules/connectors.types.ts | 148 +++++++++--------- 4 files changed, 115 insertions(+), 77 deletions(-) diff --git a/scripts/mintlify-post-processing/appended-articles.json b/scripts/mintlify-post-processing/appended-articles.json index 72a82d6..27fb69b 100644 --- a/scripts/mintlify-post-processing/appended-articles.json +++ b/scripts/mintlify-post-processing/appended-articles.json @@ -1,7 +1,8 @@ { "interfaces/ConnectorsModule": [ "type-aliases/ConnectorIntegrationType", - "interfaces/ConnectorIntegrationTypeRegistry" + "interfaces/ConnectorIntegrationTypeRegistry", + "interfaces/UserConnectorsModule" ], "type-aliases/EntitiesModule": [ "interfaces/EntityHandler", diff --git a/scripts/mintlify-post-processing/file-processing/file-processing.js b/scripts/mintlify-post-processing/file-processing/file-processing.js index 2127bd0..a3fc1e3 100755 --- a/scripts/mintlify-post-processing/file-processing/file-processing.js +++ b/scripts/mintlify-post-processing/file-processing/file-processing.js @@ -1475,6 +1475,7 @@ function mergeSectionWithMethods(content, filePath) { const lines = content.split("\n"); let modified = false; const isIntegrations = filePath && filePath.includes("integrations.mdx"); + const isConnectors = filePath && filePath.includes("connectors.mdx"); let firstMethodsFound = false; // Storage for extracted content @@ -1482,7 +1483,42 @@ function mergeSectionWithMethods(content, filePath) { let customDescription = null; let indexableContent = []; let customIntegrationsModuleDescription = []; - + + // For connectors.mdx: remove the appended user-connectors intro section and + // fold connectAppUser/disconnectAppUser into the existing ## Methods section. + if (isConnectors) { + let userConnectorsStart = -1; + let appendedMethodsStart = -1; + + for (let i = 0; i < lines.length; i++) { + if (lines[i].trim() === "## user-connectors") { + userConnectorsStart = i; + } else if (userConnectorsStart !== -1 && lines[i].trim() === "## Methods") { + appendedMethodsStart = i; + break; + } + } + + if (userConnectorsStart !== -1 && appendedMethodsStart !== -1) { + // Extract the method lines (everything after the appended ## Methods heading) + const methodLines = lines.splice(appendedMethodsStart + 1); + // Remove the appended ## user-connectors section (intro + ## Methods heading) + lines.splice(userConnectorsStart, lines.length - userConnectorsStart); + + // ## Type Definitions doesn't exist yet at this stage — groupTypeDefinitions + // creates it later from ## ConnectorIntegrationType. Insert before that heading + // so the methods land in ## Methods and the types remain in ## Type Definitions. + let insertBefore = lines.findIndex((l) => l.trim() === "## ConnectorIntegrationType"); + if (insertBefore === -1) { + // Fallback: append to end + lines.push(...methodLines); + } else { + lines.splice(insertBefore, 0, ...methodLines); + } + modified = true; + } + } + // First pass: extract type descriptions and remove sections in integrations if (isIntegrations) { for (let i = 0; i < lines.length; i++) { diff --git a/scripts/mintlify-post-processing/types-to-delete-after-processing.json b/scripts/mintlify-post-processing/types-to-delete-after-processing.json index b0df28e..dc7283e 100644 --- a/scripts/mintlify-post-processing/types-to-delete-after-processing.json +++ b/scripts/mintlify-post-processing/types-to-delete-after-processing.json @@ -3,5 +3,6 @@ "DeleteResult", "ImportResult", "SortField", - "UpdateManyResult" + "UpdateManyResult", + "user-connectors" ] diff --git a/src/modules/connectors.types.ts b/src/modules/connectors.types.ts index de4e863..bac8863 100644 --- a/src/modules/connectors.types.ts +++ b/src/modules/connectors.types.ts @@ -39,10 +39,10 @@ export interface ConnectorConnectionResponse { } /** - * Connection details for an app-user connector. + * Connection details for an app user connector. */ export interface AppUserConnectorConnectionResponse { - /** The OAuth access token for the end user's connection. */ + /** The OAuth access token for the app user's connection. */ accessToken: string; /** Key-value configuration for the connection, or `null` if the connector does not provide one. */ connectionConfig: Record | null; @@ -51,32 +51,46 @@ export interface AppUserConnectorConnectionResponse { /** * Connectors module for managing OAuth tokens for external services. * - * Use this module in **service role** mode (`base44.asServiceRole.connectors`) from server-side code. + * Unlike the {@link IntegrationsModule | integrations} module that provides pre-built functions, connectors give you raw OAuth tokens so you can call external service APIs directly. Use this when you need custom API interactions that the pre-built integrations do not cover. * - * There are two ways to obtain tokens: + * There are two connector types, depending on whether the token is shared across the app or specific to each user: * - * - **App-scoped connections** — The app builder connects an integration once; every user of the app shares that OAuth token. Call {@link getConnection} with an [integration type](#available-connectors) string (for example `'googlecalendar'` or `'slack'`). - * - **End-user (app-user) connections** — Each signed-in end user has their own OAuth token for connectors that support per-user auth. Call {@link getCurrentAppUserConnection} with the **connector ID** (the org connector's database ID), not the integration type. The API returns tokens for the user your request acts on behalf of: when the client is created with both a service token and the end user's JWT (for example via {@link createClientFromRequest | createClientFromRequest()} in a Base44 backend function), requests include the `on-behalf-of` header so the correct user's connection is resolved. + * - **[Shared connectors](#shared-connectors):** A single OAuth token shared by all app users. Best for shared service accounts. + * - **[App user connectors](#app-user-connectors):** Each app user has their own OAuth token. Best for actions that need to happen as the individual user. * - * End users start or revoke OAuth from the browser using {@link UserConnectorsModule | `base44.connectors`} (`connectAppUser` / `disconnectAppUser`). + * ## Shared connectors * - * Unlike the integrations module that provides pre-built functions, connectors give you - * raw OAuth tokens so you can call external service APIs directly with full control over - * the API calls you make. This is useful when you need custom API interactions that aren't - * covered by Base44's pre-built integrations. + * All app users share a single OAuth token. Use this for shared accounts. For example, posting to a company Slack channel or reading from a shared Google Calendar. To use a shared connector: + * + * 1. Connect the external service account in the app's Integration settings or using the [`connectors push`](/developers/references/cli/commands/connectors-push) CLI command. + * 2. In a backend function, call {@linkcode getConnection | getConnection()} using the service role client (`base44.asServiceRole.connectors`) with an [integration type](#available-connectors) string to retrieve the shared OAuth token. + * 3. Use the returned `accessToken` to call the external service's API directly. + * + * ## App user connectors + * + * Each signed-in app user has their own OAuth token. Use this when each user needs to act as themselves. For example, sending emails from their Gmail account or posting to their personal LinkedIn. To use an app user connector: + * + * 1. Register OAuth credentials for the service in Workspace Settings to get a **connector ID**. + * 2. From the frontend, call [connectAppUser()](#connectappuser) with the connector ID to get an authorization URL, then redirect the app user to that URL to complete the OAuth flow. + * 3. In a backend function, call {@linkcode getCurrentAppUserConnection | getCurrentAppUserConnection()} using the service role client (`base44.asServiceRole.connectors`) with the connector ID to retrieve the app user's token. + * 4. Use the returned `accessToken` to call the external service's API directly. * * ## Available connectors * - * For **app-scoped** tokens, pass the integration type string to {@link getConnection}. Use the returned `accessToken` (and `connectionConfig` when the connector provides extra parameters) to call the external service's API directly. + * All connectors listed below support both shared and app user connections. For shared connectors, pass the integration type string to {@linkcode getConnection | getConnection()}. For app user connectors, register the connector in Workspace Settings and use the connector ID with {@linkcode getCurrentAppUserConnection | getCurrentAppUserConnection()}. * * | Service | Type identifier | * |---|---| * | Airtable | `airtable` | + * | BambooHR | `bamboohr` | * | Box | `box` | + * | Calendly | `calendly` | * | ClickUp | `clickup` | + * | Contentful | `contentful` | * | Discord | `discord` | * | Dropbox | `dropbox` | * | GitHub | `github` | + * | GitLab | `gitlab` | * | Gmail | `gmail` | * | Google Analytics | `google_analytics` | * | Google BigQuery | `googlebigquery` | @@ -84,10 +98,14 @@ export interface AppUserConnectorConnectionResponse { * | Google Classroom | `google_classroom` | * | Google Docs | `googledocs` | * | Google Drive | `googledrive` | + * | Google Meet | `googlemeet` | * | Google Search Console | `google_search_console` | * | Google Sheets | `googlesheets` | * | Google Slides | `googleslides` | + * | Google Tasks | `googletasks` | + * | Hugging Face | `hugging_face` | * | HubSpot | `hubspot` | + * | Instagram | `instagram` | * | Linear | `linear` | * | LinkedIn | `linkedin` | * | Microsoft Teams | `microsoft_teams` | @@ -99,6 +117,7 @@ export interface AppUserConnectorConnectionResponse { * | Slack User | `slack` | * | Slack Bot | `slackbot` | * | Splitwise | `splitwise` | + * | Supabase | `supabase` | * | TikTok | `tiktok` | * | Typeform | `typeform` | * | Wix | `wix` | @@ -109,10 +128,6 @@ export interface AppUserConnectorConnectionResponse { * - **Scopes and permissions**: {@link https://docs.base44.com/Integrations/gmail-connector#gmail-scopes-and-permissions | Gmail}, {@link https://docs.base44.com/Integrations/linkedin-connector#linkedin-scopes-and-permissions | LinkedIn}, {@link https://docs.base44.com/Integrations/slack-connector#slack-scopes-and-permissions | Slack}, {@link https://docs.base44.com/Integrations/github-connector#github-scopes-and-permissions | GitHub} * - **Slack connector types**: {@link https://docs.base44.com/Integrations/slack-connector#about-the-slack-connectors | About the Slack connectors} explains the difference between `slack` and `slackbot` * - * ## Authentication Modes - * - * This module is only available to use with a client in service role authentication mode, which means it can only be used in backend environments. - * * ## Dynamic Types * * If you're working in a TypeScript project, you can generate types from your app's connector configurations to get autocomplete on integration type names when calling {@link getConnection}. See the [Dynamic Types](/developers/references/sdk/getting-started/dynamic-types) guide to get started. @@ -123,9 +138,8 @@ export interface ConnectorsModule { * * @deprecated Use {@link getConnection} instead. * - * Returns the OAuth token string for an external service that an app builder - * has connected to. This token represents the connected app builder's account - * and can be used to make authenticated API calls to that external service on behalf of the app. + * Returns the OAuth token string for an external service connected to the app. + * This token represents the connected account and can be used to make authenticated API calls to that external service on behalf of the app. * * @param integrationType - The type of integration, such as `'googlecalendar'`, `'slack'`, `'slackbot'`, `'github'`, or `'discord'`. See [Available connectors](#available-connectors) for the full list. * @returns Promise resolving to the access token string. @@ -140,11 +154,11 @@ export interface ConnectorsModule { * const timeMin = new Date().toISOString(); * const url = `https://www.googleapis.com/calendar/v3/calendars/primary/events?maxResults=10&orderBy=startTime&singleEvents=true&timeMin=${timeMin}`; * - * const calendarResponse = await fetch(url, { + * const response = await fetch(url, { * headers: { 'Authorization': `Bearer ${googleToken}` } * }); * - * const events = await calendarResponse.json(); + * const events = await response.json(); * ``` * * @example @@ -156,11 +170,11 @@ export interface ConnectorsModule { * // List all public and private channels * const url = 'https://slack.com/api/conversations.list?types=public_channel,private_channel&limit=100'; * - * const slackResponse = await fetch(url, { + * const response = await fetch(url, { * headers: { 'Authorization': `Bearer ${slackToken}` } * }); * - * const data = await slackResponse.json(); + * const data = await response.json(); * ``` * * @example @@ -189,7 +203,9 @@ export interface ConnectorsModule { getAccessToken(integrationType: ConnectorIntegrationType): Promise; /** - * Retrieves the OAuth access token and connection configuration for a specific [external integration type](#available-connectors). + * Retrieves the shared OAuth access token and connection configuration for a [shared connector](#shared-connectors) to a specific [external integration type](#available-connectors). + * + * Use this when a single shared account is connected and all app users access the same token. For per-user tokens, use [`getCurrentAppUserConnection()`](#getcurrentappuserconnection) instead. * * Some connectors require connection-specific parameters to build API calls. * In such cases, the returned `connectionConfig` is an object with the additional parameters. If there are no extra parameters needed for the connection, the `connectionConfig` is `null`. @@ -203,17 +219,13 @@ export interface ConnectorsModule { * @example * ```typescript * // Google Calendar connection - * // Get Google Calendar OAuth token and fetch upcoming events * const { accessToken } = await base44.asServiceRole.connectors.getConnection('googlecalendar'); * - * const timeMin = new Date().toISOString(); - * const url = `https://www.googleapis.com/calendar/v3/calendars/primary/events?maxResults=10&orderBy=startTime&singleEvents=true&timeMin=${timeMin}`; - * - * const calendarResponse = await fetch(url, { + * const response = await fetch('https://www.googleapis.com/calendar/v3/users/me/calendarList', { * headers: { Authorization: `Bearer ${accessToken}` } * }); * - * const events = await calendarResponse.json(); + * const { items } = await response.json(); * ``` * * @example @@ -224,11 +236,11 @@ export interface ConnectorsModule { * * const url = 'https://slack.com/api/conversations.list?types=public_channel,private_channel&limit=100'; * - * const slackResponse = await fetch(url, { + * const response = await fetch(url, { * headers: { Authorization: `Bearer ${accessToken}` } * }); * - * const data = await slackResponse.json(); + * const data = await response.json(); * ``` * * @example @@ -251,89 +263,77 @@ export interface ConnectorsModule { ): Promise; /** - * Retrieves an OAuth access token for an end user's connection to a specific connector. - * + * @internal * @deprecated Use {@link getCurrentAppUserConnection} instead. - * - * Returns the OAuth token string that belongs to the currently authenticated end user - * for the specified connector. - * - * @param connectorId - The connector ID (OrgConnector database ID). - * @returns Promise resolving to the access token string. - * - * @example - * ```typescript - * // Get the end user's access token for a connector - * const token = await base44.asServiceRole.connectors.getCurrentAppUserAccessToken('abc123def'); - * - * const response = await fetch('https://www.googleapis.com/calendar/v3/calendars/primary/events', { - * headers: { 'Authorization': `Bearer ${token}` } - * }); - * ``` */ getCurrentAppUserAccessToken(connectorId: string): Promise; /** - * Retrieves the OAuth access token and connection configuration for an end user's connection to a specific connector. + * Retrieves the OAuth access token and connection configuration for an [app user connector](#app-user-connectors). * - * Use this instead of {@link getCurrentAppUserAccessToken} when you need `connectionConfig` (for example a subdomain or other parameters the integration requires for API URLs). + * The token returned is specific to the app user making the current request. For this to work, the SDK client must know which app user to act on behalf of. Use {@linkcode createClientFromRequest | createClientFromRequest()} in a Base44 backend function to create such a client. It reads the app user's JWT from the incoming request and attaches it automatically so the runtime can resolve the correct user's connection. * - * The token belongs to the **end user the request acts on behalf of**. In practice, call from server-side code where the client was created with a service token **and** the end user's JWT so the runtime forwards an `on-behalf-of` header (for example {@link createClientFromRequest | createClientFromRequest()} in a Base44 backend function). + * The connector must be registered in Workspace Settings with OAuth credentials before this method can return a connection. The app user must also have completed the OAuth flow using [connectAppUser()](#connectappuser). * - * @param connectorId - The connector ID (OrgConnector database ID), not the integration type string. + * @param connectorId - The ID of the app user connector configured in your workspace. This is not the integration type string. You can find it on the connector's settings page in Workspace Settings. * @returns Promise resolving to an {@link AppUserConnectorConnectionResponse} with `accessToken` and `connectionConfig`. * * @example * ```typescript - * // Get the end user's connection details for a connector - * const { accessToken, connectionConfig } = await base44.asServiceRole.connectors.getCurrentAppUserConnection('abc123def'); + * // Basic usage + * const { accessToken } = await base44.asServiceRole.connectors.getCurrentAppUserConnection('abc123def'); * * const response = await fetch('https://www.googleapis.com/calendar/v3/calendars/primary/events', { * headers: { Authorization: `Bearer ${accessToken}` } * }); + * + * const data = await response.json(); * ``` * * @example * ```typescript - * // Using connectionConfig for APIs that need extra connection parameters + * // Using connectionConfig * const { accessToken, connectionConfig } = await base44.asServiceRole.connectors.getCurrentAppUserConnection('abc123def'); * * const subdomain = connectionConfig?.subdomain; - * const data = await fetch( + * const response = await fetch( * `https://${subdomain}.example.com/api/v1/resources`, * { headers: { Authorization: `Bearer ${accessToken}` } } - * ).then((r) => r.json()); + * ); + * + * const data = await response.json(); * ``` */ - getCurrentAppUserConnection(connectorId: string): Promise; + getCurrentAppUserConnection( + connectorId: string, + ): Promise; } /** - * User-scoped connectors module for managing app-user OAuth connections. + * User-scoped connectors module for managing app user OAuth connections. * - * This module provides methods for app-user OAuth flows: initiating an OAuth connection, - * retrieving the end user's access token, and disconnecting the end user's connection. + * This module provides methods for app user OAuth flows: initiating an OAuth connection and disconnecting an app user's connection. * * Unlike {@link ConnectorsModule | ConnectorsModule} which manages app-scoped tokens, - * this module manages tokens scoped to individual end users. Methods are keyed on - * the connector ID (the OrgConnector's database ID) rather than the integration type. + * this module manages tokens scoped to individual app users. Methods are keyed on + * the connector ID, not the integration type. * * Available via `base44.connectors`. */ export interface UserConnectorsModule { /** - * Initiates the app-user OAuth flow for a specific connector. + * Initiates the OAuth flow for an [app user connector](#app-user-connectors). * - * Returns a redirect URL that the end user should be navigated to in order to + * Returns a redirect URL that the app user should be navigated to in order to * authenticate with the external service. The scopes and integration type are - * derived from the connector configuration server-side. + * derived from the connector configuration in the backend. * - * @param connectorId - The connector ID (OrgConnector database ID). + * @param connectorId - The ID of the app user connector configured in your workspace. The AI builder inserts this ID into generated code when it sets up the connector flow. You can also retrieve it from the workspace connectors API. * @returns Promise resolving to the redirect URL string. * * @example * ```typescript - * // Start OAuth for the end user + * // Start OAuth for the app user * const redirectUrl = await base44.connectors.connectAppUser('abc123def'); * * // Redirect the user to the OAuth provider @@ -343,17 +343,17 @@ export interface UserConnectorsModule { connectAppUser(connectorId: string): Promise; /** - * Disconnects an end user's OAuth connection for a specific connector. + * Disconnects an app user's OAuth connection for an [app user connector](#app-user-connectors). * - * Removes the stored OAuth credentials for the currently authenticated end user's + * Removes the stored OAuth credentials for the currently authenticated app user's * connection to the specified connector. * - * @param connectorId - The connector ID (OrgConnector database ID). + * @param connectorId - The ID of the app user connector configured in your workspace. The AI builder inserts this ID into generated code when it sets up the connector flow. You can also retrieve it from the workspace connectors API. * @returns Promise resolving when the connection has been removed. * * @example * ```typescript - * // Disconnect the end user's connection + * // Disconnect the app user's connection * await base44.connectors.disconnectAppUser('abc123def'); * ``` */ From 75eefae3f000e0c2569d437205b763af4c81415c Mon Sep 17 00:00:00 2001 From: "Sam (automated drift fix)" Date: Mon, 4 May 2026 15:27:30 +0300 Subject: [PATCH 3/4] docs(connectors): note workspace admin access required for app user connector setup --- src/modules/connectors.types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/connectors.types.ts b/src/modules/connectors.types.ts index bac8863..40ef231 100644 --- a/src/modules/connectors.types.ts +++ b/src/modules/connectors.types.ts @@ -70,7 +70,7 @@ export interface AppUserConnectorConnectionResponse { * * Each signed-in app user has their own OAuth token. Use this when each user needs to act as themselves. For example, sending emails from their Gmail account or posting to their personal LinkedIn. To use an app user connector: * - * 1. Register OAuth credentials for the service in Workspace Settings to get a **connector ID**. + * 1. Register OAuth credentials for the service in Workspace Settings to get a **connector ID**. This requires workspace admin access. * 2. From the frontend, call [connectAppUser()](#connectappuser) with the connector ID to get an authorization URL, then redirect the app user to that URL to complete the OAuth flow. * 3. In a backend function, call {@linkcode getCurrentAppUserConnection | getCurrentAppUserConnection()} using the service role client (`base44.asServiceRole.connectors`) with the connector ID to retrieve the app user's token. * 4. Use the returned `accessToken` to call the external service's API directly. From 516b7f0823e942507a7790a2ffc8571ac741f503 Mon Sep 17 00:00:00 2001 From: "Sam (automated drift fix)" Date: Wed, 6 May 2026 16:12:11 +0300 Subject: [PATCH 4/4] docs(connectors): address PR review comments in connectors.types.ts - Add connectionConfig mention to shared and app user connector steps - Rename Instagram to Instagram Business to match UI - Regenerate reference docs --- src/modules/connectors.types.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/connectors.types.ts b/src/modules/connectors.types.ts index 40ef231..f7f35b2 100644 --- a/src/modules/connectors.types.ts +++ b/src/modules/connectors.types.ts @@ -64,7 +64,7 @@ export interface AppUserConnectorConnectionResponse { * * 1. Connect the external service account in the app's Integration settings or using the [`connectors push`](/developers/references/cli/commands/connectors-push) CLI command. * 2. In a backend function, call {@linkcode getConnection | getConnection()} using the service role client (`base44.asServiceRole.connectors`) with an [integration type](#available-connectors) string to retrieve the shared OAuth token. - * 3. Use the returned `accessToken` to call the external service's API directly. + * 3. Use the returned `accessToken` to call the external service's API directly. Some connectors also return a `connectionConfig` with additional values such as a subdomain for building the API URL. * * ## App user connectors * @@ -73,7 +73,7 @@ export interface AppUserConnectorConnectionResponse { * 1. Register OAuth credentials for the service in Workspace Settings to get a **connector ID**. This requires workspace admin access. * 2. From the frontend, call [connectAppUser()](#connectappuser) with the connector ID to get an authorization URL, then redirect the app user to that URL to complete the OAuth flow. * 3. In a backend function, call {@linkcode getCurrentAppUserConnection | getCurrentAppUserConnection()} using the service role client (`base44.asServiceRole.connectors`) with the connector ID to retrieve the app user's token. - * 4. Use the returned `accessToken` to call the external service's API directly. + * 4. Use the returned `accessToken` to call the external service's API directly. Some connectors also return a `connectionConfig` with additional values such as a subdomain for building the API URL. * * ## Available connectors * @@ -105,7 +105,7 @@ export interface AppUserConnectorConnectionResponse { * | Google Tasks | `googletasks` | * | Hugging Face | `hugging_face` | * | HubSpot | `hubspot` | - * | Instagram | `instagram` | + * | Instagram Business | `instagram` | * | Linear | `linear` | * | LinkedIn | `linkedin` | * | Microsoft Teams | `microsoft_teams` |