> ## Documentation Index
> Fetch the complete documentation index at: https://docs.useparagon.com/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK / API Reference

Below are all the public functions exposed on the Paragon SDK, which can be accessed as the named `paragon` export from `@useparagon/connect`, and the public endpoints of the Paragon REST API.

Install Paragon's JavaScript SDK with:

<CodeGroup>
  ```bash npm theme={null}
  npm install @useparagon/connect
  ```

  ```bash yarn theme={null}
  yarn add @useparagon/connect
  ```

  ```bash pnpm  theme={null}
  pnpm add @useparagon/connect
  ```

  ```bash bun theme={null}
  bun add @useparagon/connect
  ```
</CodeGroup>

The SDK can be imported in your client-side JavaScript files as a module:

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    import { paragon } from '@useparagon/connect';
    ```
  </Tab>
</Tabs>

<Accordion title="For on-premise users">
  If you are using an [on-premise](/on-premise/hosting-paragon-on-premise) instance of Paragon, you can call the `paragon.configureGlobal` function to point the SDK to use the base hostname of your Paragon instance.

  <Tabs>
    <Tab title="SDK" icon="js">
      ```javascript icon="js" JavaScript theme={null}
      import { paragon } from "@useparagon/connect";

      // If your login URL is https://dashboard.mycompany.paragon.so:
      paragon.configureGlobal({
        host: "mycompany.paragon.so",
      });
      ```
    </Tab>
  </Tabs>
</Accordion>

## SDK Methods

### .authenticate

`paragon.authenticate` should be called at the beginning of your application's lifecycle in all cases. This is to make sure that the `userToken` is always as fresh as possible, with respect to your user's existing session on your own site.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript  theme={null}
    await paragon.authenticate(PROJECT_ID, USER_TOKEN);
    ```
  </Tab>
</Tabs>

**Arguments:**

<ParamField path="PROJECT_ID" type="string" required>
  You can find your project ID in the Overview tab of any Integration
</ParamField>

<ParamField path="USER_TOKEN" type="string" required>
  See [Setup](/getting-started/installing-the-connect-sdk) for how to encode your user token
</ParamField>

Once `paragon.authenticate` has been called, you can access the user's integration state with `paragon.getUser`. `paragon.authenticate` only needs to be called when using the Paragon SDK - when making requests to the Paragon REST API, you should instead provide the Paragon User Token in the Authorization header.

***

### .connect

Call `paragon.connect` to launch your Connect Portal for a specific integration provider. You can find the `integrationType` identifier you need in the Overview page for the integration.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript  theme={null}
    paragon.connect(integrationType, installOptions);
    ```
  </Tab>
</Tabs>

**Arguments:**

<ParamField path="integrationType" type="string" required>
  Type of integration (i.e. "salesforce", "hubspot", "googledrive")
</ParamField>

<ParamField path="installOptions" type="InstallOptions">
  <Expandable title="Optional installOptions">
    <ParamField body="onSuccess" type="function">
      Callback invoked when an integration is successfully enabled.
    </ParamField>

    <ParamField body="onError" type="function">
      Callback if an unexpected error occurs.
    </ParamField>

    <ParamField body="accountType" type="enum">
      For integrations that support multiple account types, you can optionally designate a specific `accountType` to skip the account selection dialog.

      Example values: `default`, `sandbox`

      ```javascript icon="js" Example of using accountType theme={null}
      paragon.connect("salesforce", {
        // Only allow production-type Salesforce accounts to connect
        accountType: "default",
      });
      ```
    </ParamField>

    <ParamField body="mapObjectFields" type="object">
      For [Field Mapping](/connect-portal/field-mapping) inputs that use Dynamic Application Fields. Keys must match the Application Object Name from the dashboard; values describe application fields and/or loaders for integration object types and fields. See [Passing dynamic fields through the SDK](/connect-portal/field-mapping#passing-dynamic-fields-through-the-sdk).
    </ParamField>

    <ParamField body="externalId" type="string">
      Pass this option to associate a new credential with an identifier from your own system. The `externalId` will be available on the credential object returned by [`paragon.getUser`](/apis/api-reference#getuser).

      This option cannot be used with `selectedCredentialId`, which is used to replace or manage existing connected accounts. Existing credentials currently cannot be updated with an external ID.
    </ParamField>

    <ParamField body="selectedCredentialId" type="string">
      Used for [Multi-Account Authorization](/apis/api-reference/multi-account-authorization). Pass this option to open the Connect Portal for an existing credential ID and update/manage settings (headful) or to start an install flow to replace an existing credential ID with a new account (with the [Headless Connect Portal](/connect-portal/headless-connect-portal)).
    </ParamField>

    <ParamField body="selectedConfigurationId" type="string">
      Used for [Multi-Configuration](/apis/api-reference/multi-configuration). Pass this option to open the Connect Portal for a specific configuration (unique set of User Settings and Workflow Enablements for a connected credential).
    </ParamField>
  </Expandable>
</ParamField>

This function must be called after the Paragon SDK has completed authentication. You can `await` the Promise returned by [`paragon.authenticate`](#authenticate) to show a loading state before users are able to access the Connect Portal.

You *must* have an integration configured of this `integrationType` in your Paragon project for the Connect Portal to appear. Otherwise, this function does nothing.

If your integration uses a [Field Mapping](/connect-portal/field-mapping) User Setting, pass the mapping configuration through `installOptions`. For examples, see [Passing dynamic fields through the SDK](/connect-portal/field-mapping#passing-dynamic-fields-through-the-sdk).

You can also connect multiple accounts for the same integration.

<Card title="Multi Account Authorization" href="/apis/api-reference/multi-account-authorization" horizontal arrow />

***

### .subscribe

Call `paragon.subscribe` to subscribe to different events and changes from the Paragon SDK. You can find the possible `eventNames` below:

| Event Type                | Usage in `paragon.subscribe` | Usage in `paragon.connect` |
| ------------------------- | ---------------------------- | -------------------------- |
| **Integration enabled**   | `"onIntegrationInstall"`     | `"onInstall"`              |
| **Integration disabled**  | `"onIntegrationUninstall"`   | `"onUninstall"`            |
| **Workflow state change** | `"onWorkflowChange"`         | `"onWorkflowChange"`       |
| **Connect Portal opened** | `"onPortalOpen"`             | `"onOpen"`                 |
| **Connect Portal closed** | `"onPortalClose"`            | `"onClose"`                |

Subscribing to SDK Events applies to all integrations *globally*. Specifying callbacks to `paragon.connect` only applies to a currently open Connect Portal *locally*.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    paragon.subscribe(eventType, callback);
    ```
  </Tab>
</Tabs>

<ParamField body="eventType" type="string">
  Event type (i.e. "onIntegrationInstall", "onPortalOpen") as seen in the table above
</ParamField>

<ParamField body="callback" type="(event: Event, user: AuthenticatedConnectUser) => void">
  callback function that triggers on event
</ParamField>

**Examples:**

<CodeGroup>
  ```typescript Integration Enabled / Disabled theme={null}
  type IntegrationInstallEvent = {
    integrationId: string;
    integrationType: VisibleConnectAction;
    credential: Credential;
    credentialId: string;
  };

  // Using global subscribe
  paragon.subscribe(
    "onIntegrationInstall",
    (event: IntegrationInstallEvent, user: AuthenticatedConnectUser) => {
      /* ... */
    }
  );
  ```

  ```typescript Workflow State Changed theme={null}
  type WorkflowStateChangeEvent = {
    integrationId: string;
    workflowId: string;
  };

  // Using global subscribe
  paragon.subscribe(
    "onWorkflowChange",
    (event: WorkflowStateChangeEvent, user: AuthenticatedConnectUser) => {
      /* ... */
    }
  );
  ```

  ```typescript Connect Portal Opened / Closed theme={null}
  type PortalOpenEvent = {
    integrationId: string;
    integrationType: VisibleConnectAction;
  };

  type PortalCloseEvent = {
    integrationId: string;
    integrationType: VisibleConnectAction;
  };

  // Using global subscribe
  paragon.subscribe(
    "onPortalOpen",
    (event: PortalOpenEvent, user: AuthenticatedConnectUser) => {
      /* ... */
    }
  );
  paragon.subscribe(
    "onPortalClose",
    (event: PortalCloseEvent, user: AuthenticatedConnectUser) => {
      /* ... */
    }
  );
  ```
</CodeGroup>

Alternatively, you can subscribe `onOpen`, `onClose`, `onUninstall` , and `onWorkflowChange` as a one-time event locally.

<CodeGroup>
  ```typescript Integration Enabled / Disabled theme={null}
  type IntegrationInstallEvent = {
    integrationId: string;
    integrationType: VisibleConnectAction;
    credential: Credential;
    credentialId: string;
  };

  // Using local call to paragon.connect
  paragon.connect("<integration>", {
    onInstall: (
      event: IntegrationInstallEvent,
      user: AuthenticatedConnectUser
    ) => {
      /* ... */
    },
  });
  ```

  ```typescript Workflow State Changed theme={null}
  type WorkflowStateChangeEvent = {
    integrationId: string;
    workflowId: string;
  };

  // Using local call to paragon.connect
  paragon.connect("<integration>", {
    onWorkflowChange: (
      event: WorkflowStateChangeEvent,
      user: AuthenticatedConnectUser
    ) => {
      /* ... */
    },
  });
  ```

  ```typescript Connect Portal Opened / Closed theme={null}
  type PortalOpenEvent = {
    integrationId: string;
    integrationType: VisibleConnectAction;
  };

  type PortalCloseEvent = {
    integrationId: string;
    integrationType: VisibleConnectAction;
  };

  // Using local call to paragon.connect
  paragon.connect("<integration>", {
    onOpen: (event: PortalOpenEvent, user: AuthenticatedConnectUser) => {
      /* ... */
    },
    onClose: (event: PortalCloseEvent, user: AuthenticatedConnectUser) => {
      /* ... */
    },
  });
  ```
</CodeGroup>

***

### .installIntegration

<Info>
  This function should be used only if you are using your [own components](/connect-portal/headless-connect-portal) to show connected integrations and their status, instead of the Connect Portal.

  Otherwise, you can use [the `paragon.connect` function](/apis/api-reference#connect).
</Info>

The `paragon.installIntegration` can be used to start the connection process for an integration *without* the Connect Portal appearing over your user interface. You can find the `integrationType` identifier you need in the Overview page for the integration.

This function resolves with the `IntegrationInstallEvent` in the same format available in `paragon.subscribe`. You can use this to get the newly created credential by awaiting the returned Promise.

This function rejects the returned Promise if the integration is already installed for the authenticated user.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript  theme={null}
    const { credential } = await paragon.installIntegration(integrationType, installOptions);
    ```
  </Tab>
</Tabs>

<ParamField path="integrationType" type="string" required>
  Type of integration (i.e. "salesforce", "hubspot", "googledrive")
</ParamField>

<ParamField path="installOptions" type="InstallOptions">
  <Expandable title="Optional installOptions">
    <ParamField body="onSuccess" type="function">
      Callback invoked when an integration is successfully enabled.
    </ParamField>

    <ParamField body="onError" type="function">
      Callback if an unexpected error occurs.
    </ParamField>

    <ParamField body="accountType" type="enum">
      For integrations that support multiple account types, you can optionally designate a specific `accountType` to skip the account selection dialog.

      Example values: `default`, `sandbox`

      ```javascript icon="js" Example of using accountType theme={null}
      paragon.connect("salesforce", {
        // Only allow production-type Salesforce accounts to connect
        accountType: "default",
      });
      ```
    </ParamField>

    <ParamField body="mapObjectFields" type="object">
      For [Field Mapping](/connect-portal/field-mapping) inputs that use Dynamic Application Fields. Keys must match the Application Object Name from the dashboard; values describe application fields and/or loaders for integration object types and fields. See [Passing dynamic fields through the SDK](/connect-portal/field-mapping#passing-dynamic-fields-through-the-sdk).
    </ParamField>

    <ParamField body="externalId" type="string">
      Pass this option to associate a new credential with an identifier from your own system. The `externalId` will be available on the credential object returned by [`paragon.getUser`](/apis/api-reference#getuser).

      This option cannot be used with `selectedCredentialId`, which is used to replace or manage existing connected accounts. Existing credentials currently cannot be updated with an external ID.
    </ParamField>

    <ParamField body="selectedCredentialId" type="string">
      Used for [Multi-Account Authorization](/apis/api-reference/multi-account-authorization). Pass this option to open the Connect Portal for an existing credential ID and update/manage settings (headful) or to start an install flow to replace an existing credential ID with a new account (with the [Headless Connect Portal](/connect-portal/headless-connect-portal)).
    </ParamField>

    <ParamField body="selectedConfigurationId" type="string">
      Used for [Multi-Configuration](/apis/api-reference/multi-configuration). Pass this option to open the Connect Portal for a specific configuration (unique set of User Settings and Workflow Enablements for a connected credential).
    </ParamField>
  </Expandable>
</ParamField>

**Note**: If the integration specified by `integrationType` requires API keys or post-authentication options, the Connect Portal will still appear to capture those values from your user at that time. The Connect Portal will automatically be dismissed after those values are entered.

This function accepts the same optional install options as [`paragon.connect`](/apis/api-reference#connect).

***

### .uninstallIntegration

Call `paragon.uninstallIntegration` to disconnect an integration for the authenticated user.

When an integration is disconnected, workflows for that integration will stop running for the authenticated user and any saved User Settings will be cleared.

<Tabs>
  <Tab title="SDK" icon="js">
    ```typescript JavaScript SDK theme={null}
    await paragon.uninstallIntegration(integrationType);
    ```

    **Arguments:**

    <ParamField path="integrationType" type="string" required>
      The short name for the integration (i.e. "salesforce", "hubspot"). Use the same name as used in `paragon.connect`.
    </ParamField>
  </Tab>

  <Tab title="REST API" icon="terminal">
    ```http icon="terminal" HTTP theme={null}
    GET https://api.useparagon.com/projects/PROJECT_ID/sdk/integrations

    Authorization: Bearer <Paragon User Token>

    // Example Response
    // [ { "id": INTEGRATION_ID, "type": "salesforce"} ]

    DELETE https://api.useparagon.com/projects/PROJECT_ID/sdk/integrations/INTEGRATION_ID

    Authorization: Bearer PARAGON_USER_TOKEN
    ```

    **Arguments:**

    <ParamField path="PROJECT_ID" type="string" required>
      You can find your project ID in the Overview tab of any Integration
    </ParamField>

    <ParamField path="INTEGRATION_ID" type="string" required>
      The ID of the integration to disconnect. Retrieve it from the `/sdk/integrations` endpoint.
    </ParamField>

    <ParamField path="PARAGON_USER_TOKEN" type="string" required>
      See [Setup](/getting-started/installing-the-connect-sdk) for how to encode your user token
    </ParamField>
  </Tab>
</Tabs>

***

### .getIntegrationMetadata

Call `paragon.getIntegrationMetadata` to get the `name`, `brandColor`, and `icon`, for any of your active integration providers. This is a great way to create your integrations page!

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    paragon.getIntegrationMetadata();
    ```
  </Tab>

  <Tab title="REST API" icon="terminal">
    ```http icon="terminal" HTTP theme={null}
    GET https://api.useparagon.com/projects/PROJECT_ID/sdk/metadata

    Authorization: Bearer PARAGON_USER_TOKEN
    ```

    **Arguments:**

    <ParamField path="PROJECT_ID" type="string" required>
      You can find your project ID in the Overview tab of any Integration
    </ParamField>

    <ParamField path="PARAGON_USER_TOKEN" type="string" required>
      See [Setup](/getting-started/installing-the-connect-sdk) for how to encode your user token
    </ParamField>
  </Tab>
</Tabs>

**Returns:**

<ParamField path="data" type="object[]" required>
  <Expandable title="child properties">
    <ParamField path="type" type="string" required>
      The integration type identifier (e.g., `"salesforce"`, `"hubspot"`).
    </ParamField>

    <ParamField path="name" type="string" required>
      The human-readable display name of the integration.
    </ParamField>

    <ParamField path="brandColor" type="string" required>
      The brand color hex value for the integration.
    </ParamField>

    <ParamField path="icon" type="string" required>
      The URL to the integration's icon image.
    </ParamField>
  </Expandable>
</ParamField>

**Example Response:**

```javascript icon="js" JavaScript expandable theme={null}
[
  {
    "type": "salesforce",
    "name": "Salesforce",
    "brandColor": "#057ACF",
    "icon": "https://cdn.useparagon.com/2.35.0/dashboard/public/integrations/salesforce.svg"
  },
  {
    "type": "hubspot",
    "name": "Hubspot",
    "brandColor": "#F67600",
    "icon": "https://cdn.useparagon.com/2.35.0/dashboard/public/integrations/hubspot.svg"
  },
  {
    "type": "slack",
    "name": "Slack",
    "brandColor": "#4A154B",
    "icon": "https://cdn.useparagon.com/2.35.0/dashboard/public/integrations/slack.svg"
  }
]
```

***

### .getIntegrationConfig

Call `paragon.getIntegrationConfig` to get the user-facing descriptions, User Settings, and Workflows associated with any integration.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    paragon.getIntegrationConfig(integrationType);
    ```

    **Arguments:**

    <ParamField path="integrationType" type="string" required>
      An integration type string, like `salesforce` or `slack`.
    </ParamField>

    **Example Response:**

    ```javascript icon="js" JavaScript expandable theme={null}
    {
      "shortDescription": "Send notifications to Slack",
      "longDescription": "Connect your Slack workspace to receive notifications and alerts in Slack. Stay connected to important activity by bringing it all together in your Slack workspace.\n\nOur Slack integration enables you to:\n\n• Receive alerts and notifications in your Slack workspace\n• Notify or DM specific team members based on certain activity",
      "availableUserSettings": [
        {
          "id": "2d5662c9-6750-46c2-8588-2ac904532efb",
          "type": "DYNAMIC_ENUM",
          "title": "Channel",
          "required": false,
          "sourceType": "channels"
        }
      ],
      "availableWorkflows": [
        {
          "id": "2248335c-671c-47e4-b9a0-3641a9f2d301",
          "inputs": [],
          "infoText": "Send a Slack notification when a Task is created",
          "defaultEnabled": false,
          "description": "Send Slack Notification"
        }
      ],
      "hiddenWorkflows": []
    }
    ```
  </Tab>

  <Tab title="REST API" icon="terminal">
    ```http icon="terminal" HTTP theme={null}
    GET https://api.useparagon.com/projects/PROJECT_ID/sdk/integrations/INTEGRATION_TYPE

    Authorization: Bearer PARAGON_USER_TOKEN
    ```

    **Arguments:**

    <ParamField path="PROJECT_ID" type="string" required>
      You can find your project ID in the Overview tab of any Integration
    </ParamField>

    <ParamField path="INTEGRATION_TYPE" type="string" required>
      An integration type string, like `salesforce` or `slack`.
    </ParamField>

    <ParamField path="PARAGON_USER_TOKEN" type="string" required>
      See [Setup](/getting-started/installing-the-connect-sdk) for how to encode your user token
    </ParamField>

    **Example Response:**

    ```javascript icon="js" JavaScript expandable theme={null}
    [{
      "id": "2f08e65f-d924-42ab-9618-b6023d82ffbd",
      "projectId": "908f4c5e-6394-46a5-9355-3f729edbd160",
      "customIntegrationId": null,
      "type": "slack",
      "isActive": true,
      "configs": [
        {
          "id": "3ebcc179-a1a6-447f-8dc9-5017f40f08ef",
          "values": {
            "overview": "####Our Slack integration enables you to:\n   \n\n• Receive alerts and notifications in your Slack workspace\n• Notify or DM specific team members based on certain activity",
            "sharedMeta": {},
            "accentColor": "#4A154B",
            "description": "Send notifications to Slack",
            "workflowMeta": {}
          }
        },
      ],
      "workflows": [
        {
          "id": "1b22193b-e355-458d-b6a3-5e5516edb588",
          "description": "Send Updates to Slack",
          "projectId": "908f4c5e-6394-46a5-9355-3f729edbd160",
          "integrationId": "2f08e65f-d924-42ab-9618-b6023d82ffbd",
          "steps": []
        }
      ],
      "customIntegration": null,
      "hasCredential": true,
      "connectedUserLimitOnDevCred": 0,
      "connectedUserLimitReached": true,
      "name": "Slack",
      "brandColor": "#4A154B",
      "needPreOauthInputs": false,
      "providerType": "slack",
      "authenticationType": "oauth"
    }]
    ```
  </Tab>
</Tabs>

***

### .getUser

Call `paragon.getUser` to retrieve the currently authenticated user and their connected integration state.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    paragon.getUser();
    ```
  </Tab>

  <Tab title="REST API" icon="terminal">
    ```http icon="terminal" HTTP theme={null}
    GET https://api.useparagon.com/projects/PROJECT_ID/sdk/me

    Authorization: Bearer PARAGON_USER_TOKEN
    ```

    **Arguments:**

    <ParamField path="PROJECT_ID" type="string" required>
      You can find your project ID in the Overview tab of any Integration
    </ParamField>

    <ParamField path="PARAGON_USER_TOKEN" type="string" required>
      See [Setup](/getting-started/installing-the-connect-sdk) for how to encode your user token
    </ParamField>
  </Tab>
</Tabs>

**Example Response:**

```javascript icon="js" JavaScript expandable theme={null}
{
  authenticated: true,
  userId: "xyz",
  integrations: {
    salesforce: {
      configuredWorkflows: {},
      credentialId: "987654-56a7-89b1-cd23-456789abcdef",
      credentialStatus: "VALID",
      enabled: true,
      providerData: {
        instanceURL: "https://mycompany.my.salesforce.com"
      },
      providerId: "1234567890"
    },
    shopify: {
      configuredWorkflows: {},
      enabled: false
    }
  }
}
```

If the user is not authenticated, you'll receive back only `{ authenticated: false }` instead. Please check the `authenticated` property before using the `user.integrations` field.

***

### .setUserMetadata

Call `paragon.setUserMetadata` to associate the authenticated user with metadata from your application. This metadata can be accessed with `paragon.getUser` or retrieved over the API.

<Tabs>
  <Tab title="SDK" icon="js">
    ```typescript JavaScript SDK theme={null}
    paragon.setUserMetadata(metadata);
    ```

    **Arguments:**

    <ParamField path="metadata" type="object" required>
      Metadata object to associate with the authenticated user.
    </ParamField>
  </Tab>

  <Tab title="REST API" icon="terminal">
    ```http icon="terminal" HTTP theme={null}
    PATCH https://api.useparagon.com/projects/PROJECT_ID/sdk/me

    // Headers
    Authorization: PARAGON_USER_TOKEN
    Content-Type: application/json

    // Body
    { ...metadata }
    ```

    **Arguments:**

    <ParamField path="PROJECT_ID" type="string" required>
      You can find your project ID in the Overview tab of any Integration
    </ParamField>

    <ParamField path="PARAGON_USER_TOKEN" type="string" required>
      See [Setup](/getting-started/installing-the-connect-sdk) for how to encode your user token
    </ParamField>

    <ParamField path="metadata" type="object" required>
      Metadata object to associate with the authenticated user.
    </ParamField>
  </Tab>
</Tabs>

**Examples:**

<CodeGroup>
  ```typescript JavaScript SDK theme={null}
  paragon.setUserMetadata({
    Name: "Sean V",
    Email: "sean@useparagon.com",
    apiKey: "key_Y0kBVldPFInxK",
  });
  ```

  **Request**

  ```http icon="terminal" HTTP theme={null}
  PATCH https://api.useparagon.com/projects/<Project ID>/sdk/me

  // Headers
  Authorization: <Paragon User Token>
  Content-Type: application/json

  // Body
  { "meta": { "Email": "sean@useparagon.com", "apiKey": "key_Y0kBVldPFInxK" } }
  ```
</CodeGroup>

***

### .updateIntegrationUserSettings

Call `paragon.updateIntegrationUserSettings` to update any integration-level [User Settings](/connect-portal/workflow-user-settings) for your Connected User.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    paragon.updateIntegrationUserSettings(integrationType, userSettingsUpdate, options);
    ```
  </Tab>
</Tabs>

**Arguments:**

<ParamField path="integrationType" type="string" required>
  An integration type string, like `salesforce`.
</ParamField>

<ParamField path="userSettingsUpdate" type="object" required>
  A partial update object where the keys are the `id` properties of User Settings objects (which you can get from [`paragon.getIntegrationConfig`](#getintegrationconfig)) and the values are the user's selection for the matching input type.

  Any keys that are not included in the object will not be updated.

  The type for each value will depend on the input type. See [Input Types Reference](/connect-portal/input-types-reference) to see the value type for each input.

  ```json Example theme={null}
  {
    "1f7474a5-8b8e-4c25-8d44-29f20aec3fe4": "general"
  }
  ```
</ParamField>

<ParamField path="options" type="CredentialConfigOptions | undefined">
  Optionally specify a Credential and Configuration to target, if using [Multi-Account Authorization](/apis/api-reference/multi-account-authorization) or [Multi-Configuration](/apis/api-reference/multi-configuration).

  <Accordion title="Show child properties">
    <ParamField path="selectedCredentialId" type="string">
      The Credential ID (a UUID) of the connected account you want to update, if using [Multi-Account Authorization](/apis/api-reference/multi-account-authorization).
    </ParamField>

    <ParamField path="selectedConfigurationId" type="string">
      The Configuration ID (a UUID or an External ID prefixed with `ext:`), if using [Multi-Configuration](/apis/api-reference/multi-configuration).
    </ParamField>
  </Accordion>
</ParamField>

***

### .getDataSourceOptions

Call `paragon.getDataSourceOptions` to get configuration details for **compound** data sources used for dynamic [User Settings types](/connect-portal/headless-connect-portal#exposing-user-settings) in the Headless Connect Portal.

Compound data sources, for Field Mapping and Combo Dropdown inputs, have multiple data sources within them (Field Mappings have both Object Types and Field Names as sources).

To load options for a data source, see [`paragon.getFieldOptions`](#getfieldoptions).

<Info>
  **SDK 2.3.0+:** Consider using [`paragon.getSourcesForInput`](#getsourcesforinput) instead, which provides a simpler way to get all data sources needed for any input type in a single call.
</Info>

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript  theme={null}
    await paragon.getDataSourceOptions(integrationType, sourceType);
    ```
  </Tab>
</Tabs>

**Arguments:**

<ParamField path="integrationType" type="string" required>
  An integration type string, like `salesforce`.
</ParamField>

<ParamField path="sourceType" type="string" required>
  A source type string, which can be found in the `sourceType` property of a
  User Setting object from [`paragon.getIntegrationConfig`](#getintegrationconfig) or
  from `stage.options` of `PostOptionsStage`.
</ParamField>

**Examples:**

<CodeGroup>
  ```javascript icon="js" JavaScript SDK (Field Mapping) expandable theme={null}
  await paragon.getDataSourceOptions(
    "salesforce",
    "customObjectMapping",
  );

  // Returns:
  {
    "id": "customObjectMapping",
    "type": "FIELD_MAPPER_DATA_SOURCE",
    "title": "Field Mapping",
    "subtitle": "Allows users to define a field mapping",
    "recordSource": {
      "type": "DYNAMIC_DATA_SOURCE",
      "title": "Record Type",
      "cacheKey": "recordTypes",
    },
    "fieldSource": {
      "type": "DYNAMIC_DATA_SOURCE",
      "title": "Field",
      "cacheKey": "cachedFields",
    },
  }
  ```

  ```javascript icon="js" JavaScript SDK (Combo Dropdown) expandable theme={null}
  await paragon.getDataSourceOptions(
    "jira",
    "projectIssueStatusTypeCombo",
  );

  // Returns:
  {
    "id": "projectIssueStatusTypeCombo",
    "type": "COMBO_INPUT_DATA_SOURCE",
    "title": "Issue Status",
    "subtitle": "The stage the issue is at, e.g. To Do or Done",
    "mainInputSource": {
      "type": "DYNAMIC_DATA_SOURCE",
      "cacheKey": "projects",
      "title": "Project",
      "subtitle": "Jira project that issues can be created in",
    },
    "dependentInputSource": {
      "type": "DYNAMIC_DATA_SOURCE",
      "cacheKey": "issueIssueStatusByProject",
      "title": "Issue Status",
      "subtitle": "The stage the issue is at, e.g. To Do or Done",
    }
  }
  ```
</CodeGroup>

***

### .getFieldOptions

Load options from an integration data source for dynamic [User Settings types](/connect-portal/headless-connect-portal#exposing-user-settings) in the Headless Connect Portal, using the Connected User's account.

**`paragon.getFieldOptions` can only be called for data sources with type `DYNAMIC_DATA_SOURCE`** (for dynamic enum input types).

* Compound data sources like `FIELD_MAPPER_DATA_SOURCE` or `COMBO_INPUT_DATA_SOURCE` are composed of `DYNAMIC_DATA_SOURCE`-type sources.

* When rendering Field Mapping or Combo Dropdown inputs, first identify each data source with [`paragon.getSourcesForInput`](#getsourcesforinput) (or [`paragon.getDataSourceOptions`](#getdatasourceoptions)), and use the returned data source configuration to call `paragon.getFieldOptions`. [See a full example.](/connect-portal/headless-connect-portal#exposing-user-settings)

This function supports search and pagination; see the parameters for `fieldOptions` below to learn more.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript SDK (Field Mapping) theme={null}
      await paragon.getFieldOptions(fieldOptions);
    ```

    **Arguments:**

    <ParamField path="fieldOptions" type="FieldOptions" required>
      <Expandable title="child properties">
        <ParamField path="integration" type="string" required>
          An integration type string, like `salesforce`.
        </ParamField>

        <ParamField path="action" type="string">
          A source type string, which can be found in the `sourceType` property of a User Setting object from [`paragon.getIntegrationConfig`](#getintegrationconfig) or from `stage.options` of `PostOptionsStage`.

          Either `action` or `source` must be provided.
        </ParamField>

        <ParamField path="source" type="DynamicDataSource">
          A `DynamicDataSource` object, as returned by [`paragon.getSourcesForInput`](#getsourcesforinput). When provided, the `cacheKey` of the source is used to identify the data source to load options from.

          Either `action` or `source` must be provided.
        </ParamField>

        <ParamField path="search" type="string">
          A user-provided search query for an option. When provided, the data source will return options that match this query.
        </ParamField>

        <ParamField path="cursor" type="string">
          A page cursor to use to load subsequent pages of results. The response of `paragon.getFieldOptions` will provide `nextPageCursor` to use or `null` if there are no more results.
        </ParamField>

        <ParamField path="parameters" type="Parameter[]">
          When loading options for a compound data source (e.g. `fieldSource` of a Field Mapping input or `dependentInputSource` of a Combo Dropdown input), pass parameters with the user's selection from the first input (e.g. the Record Type for Field Mapping).

          <Expandable title="child properties">
            <ParamField path="key" type="string">
              The `cacheKey` property of the primary/first input in the compound data sources (e.g. `recordSource` of a Field Mapping input or `mainInputSource` of a Combo Dropdown input).
            </ParamField>

            <ParamField path="source" type="string">
              <Expandable title="child properties">
                <ParamField path="type" type="const" required>
                  Set this to `"VALUE"`.
                </ParamField>

                <ParamField path="value" type="string" required>
                  Set this to the `value` property of the user's selection.
                </ParamField>
              </Expandable>
            </ParamField>
          </Expandable>
        </ParamField>

        <ParamField path="selectedCredentialId" type="string">
          If you are using [Multi-Account Authorization](/apis/api-reference/multi-account-authorization) and there may be more than one account connected for a given integration, pass `selectedCredentialId` to load options for the current account.
        </ParamField>
      </Expandable>
    </ParamField>
  </Tab>

  <Tab title="REST API" icon="terminal">
    ```http icon="terminal" HTTP theme={null}
    POST https://api.useparagon.com/projects/PROJECT_ID/sdk/actions

    Authorization: Bearer PARAGON_USER_TOKEN
    Content-Type: application/json

    {
      ...fieldOptions
    }
    ```

    **Arguments:**

    <ParamField path="PROJECT_ID" type="string" required>
      You can find your project ID in the Overview tab of any Integration
    </ParamField>

    <ParamField path="PARAGON_USER_TOKEN" type="string" required>
      See [Setup](/getting-started/installing-the-connect-sdk) for how to encode your user token
    </ParamField>

    <ParamField path="fieldOptions" type="FieldOptions" required>
      <Expandable title="child properties">
        <ParamField path="integration" type="string" required>
          An integration type string, like `salesforce`.
        </ParamField>

        <ParamField path="action" type="string">
          A source type string, which can be found in the `sourceType` property of a User Setting object from [`paragon.getIntegrationConfig`](#getintegrationconfig) or from `stage.options` of `PostOptionsStage`.

          Either `action` or `source` must be provided.
        </ParamField>

        <ParamField path="source" type="DynamicDataSource">
          A `DynamicDataSource` object, as returned by [`paragon.getSourcesForInput`](#getsourcesforinput). When provided, the `cacheKey` of the source is used to identify the data source to load options from.

          Either `action` or `source` must be provided.
        </ParamField>

        <ParamField path="search" type="string">
          A user-provided search query for an option. When provided, the data source will return options that match this query.
        </ParamField>

        <ParamField path="cursor" type="string">
          A page cursor to use to load subsequent pages of results. The response of `paragon.getFieldOptions` will provide `nextPageCursor` to use or `null` if there are no more results.
        </ParamField>

        <ParamField path="parameters" type="Parameter[]">
          When loading options for a compound data source (e.g. `fieldSource` of a Field Mapping input or `dependentInputSource` of a Combo Dropdown input), pass parameters with the user's selection from the first input (e.g. the Record Type for Field Mapping).

          <Expandable title="child properties">
            <ParamField path="key" type="string">
              The `cacheKey` property of the primary/first input in the compound data sources (e.g. `recordSource` of a Field Mapping input or `mainInputSource` of a Combo Dropdown input).
            </ParamField>

            <ParamField path="source" type="string">
              <Expandable title="child properties">
                <ParamField path="type" type="const" required>
                  Set this to `"VALUE"`.
                </ParamField>

                <ParamField path="value" type="string" required>
                  Set this to the `value` property of the user's selection.
                </ParamField>
              </Expandable>
            </ParamField>
          </Expandable>
        </ParamField>

        <ParamField path="selectedCredentialId" type="string">
          If you are using [Multi-Account Authorization](/apis/api-reference/multi-account-authorization) and there may be more than one account connected for a given integration, pass `selectedCredentialId` to load options for the current account.
        </ParamField>
      </Expandable>
    </ParamField>
  </Tab>
</Tabs>

**Returns:**

<ParamField path="data" type="Option[] | Section[]" required>
  <Expandable title="child properties">
    `data` will be an Array of either `Option` or `Section` objects, which should be handled by your Dropdown input.

    <Tabs>
      <Tab title="Option">
        <ParamField path="label" type="string" required>
          The human-readable display name to use for this option when displaying
          it to your user.
        </ParamField>

        <ParamField path="value" type="string" required>
          The unique value of this option to save with `paragon.setPreOptions`,
          `paragon.setPostOptions`, `paragon.updateIntegrationUserSettings`, or
          `paragon.updateWorkflowUserSettings`. This value can also be passed as
          `parameters[].source.value` for dependent inputs of compound data
          sources.
        </ParamField>
      </Tab>

      <Tab title="Section">
        <ParamField path="title" type="string" required>
          The title of this section of options.
        </ParamField>

        <ParamField path="items" type="Option[]" required>
          The list of options that should be contained in this section.
        </ParamField>
      </Tab>
    </Tabs>
  </Expandable>
</ParamField>

<ParamField path="nestedData" type="object[]">
  This section is an empty array for all input types except for **Default value mapping**, which is only supported by Jira: Issue Field Values.
</ParamField>

<ParamField path="nextPageCursor" type="string | null">
  The cursor value to pass as `cursor` for the next page of results.
</ParamField>

**Examples:**

<CodeGroup>
  ```javascript icon="js" JavaScript SDK expandable theme={null}
  await paragon.getFieldOptions({
    integration: "slack",
    action: "channels",
    search: "general",
  });

  // Returns:
  {
    "data": [
      {
        "label": "#general",
        "value": "general"
      },
    ],
    "nestedData": [],
    "nextPageCursor": "dGVhbTpDMDUxWjlNSzk4Vw=="
  }
  ```

  ```javascript icon="js" JavaScript SDK (Field Mapping) expandable theme={null}
  // Load Record Types:
  await paragon.getFieldOptions({
    integration: "salesforce",
    action: "recordTypes", // from `recordSource.cacheKey` of data source options
  });

  // Load Fields: 
  await paragon.getFieldOptions({
    integration: "salesforce",
    action: "cachedFields", // from `fieldSource.cacheKey` of data source options
    parameters: [{
      "key": "recordTypes",
      "source": {
        "type": "VALUE",
        "value": "Task" // The `value` property of the user's input
      }
    }],
  });
  ```

  REST API

  ```http icon="terminal" HTTP theme={null}
  POST https://api.useparagon.com/projects/<Paragon Project ID>/sdk/actions

  Authorization: Bearer <Paragon User Token>
  Content-Type: application/json

  {
    "action": "salesforce",
    "sourceKey": "cachedFields",
    "parameters": [{
      "key": "recordTypes",
      "source": {
        "type": "VALUE",
        "value": "Task"
      }
    }],
    "paginationParameters": {
      "pageCursor": 0,
      "search": ""
    }
  }
  ```
</CodeGroup>

***

### .getSourcesForInput

Call `paragon.getSourcesForInput` to get all the data sources needed to render a dynamic input (e.g. a picklist loaded from integration data from the user's connected account).

The returned data sources can be passed directly to [`paragon.getFieldOptions`](#getfieldoptions) using the `source` parameter to load options for your input, with pagination and search.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    const config = paragon.getIntegrationConfig(integrationType, input);
    ```
  </Tab>
</Tabs>

**Arguments:**

<ParamField path="integrationType" type="string" required>
  An integration type string, like `salesforce`.
</ParamField>

<ParamField path="input" type="Input" required>
  The input object from `availableUserSettings`, `availableWorkflows[n].inputs`, or `stage.options` of an install flow stage.
</ParamField>

**Returns:**

Returns `null` for inputs that don't require a data source (e.g. text inputs). Otherwise, returns one of the following based on the [Input Type](/connect-portal/input-types-reference) of the input:

<Tabs>
  <Tab title="SingleSource">
    Returned for [`DynamicEnum`](/connect-portal/input-types-reference) and [`CustomDropdown`](/connect-portal/input-types-reference) input types.

    <ParamField path="kind" type="const" required>
      `"single"` for SingleSource.
    </ParamField>

    <ParamField path="source" type="DynamicDataSource | StaticEnumDataSource" required>
      The data source for the input. Pass this to [`paragon.getFieldOptions`](#getfieldoptions) using the `source` parameter to load options.
    </ParamField>

    **Example:**

    ```javascript icon="js" DynamicEnum input expandable theme={null}
    const config = paragon.getIntegrationConfig("slack");
    const input = config.availableUserSettings[0];
    // { id: "...", type: "DYNAMIC_ENUM", title: "Channel", sourceType: "channels" }

    const sources = paragon.getSourcesForInput("slack", input);
    // { kind: "single", source: { type: "DYNAMIC_DATA_SOURCE", cacheKey: "channels", ... } }

    if (sources?.kind === "single") {
      const options = await paragon.getFieldOptions({
        integration: "slack",
        source: sources.source,
      });
      // { data: [{ label: "#general", value: "general" }, ...], nextPageCursor: "..." }
    }
    ```
  </Tab>

  <Tab title="FieldMapperSources">
    Returned for [`FieldMapper`](/connect-portal/input-types-reference) input types.

    <ParamField path="kind" type="const" required>
      `"fieldMapper"` for FieldMapperSources.
    </ParamField>

    <ParamField path="recordSource" type="DynamicDataSource" required>
      The data source for loading record types. Pass to [`paragon.getFieldOptions`](#getfieldoptions) to load record type options.
    </ParamField>

    <ParamField path="fieldSource" type="DynamicDataSource" required>
      The data source for loading fields. Pass to [`paragon.getFieldOptions`](#getfieldoptions) with `parameters` for the selected record type to load available fields.
    </ParamField>

    <ParamField path="dependentInputSource" type="DynamicDataSource">
      An optional data source for a dependent input within the field mapping.
    </ParamField>

    <ParamField path="mapObjectFieldOptions" type="DynamicMappingOptions | DynamicMappingField[]">
      Pre-configured field mapping options, if provided via [`paragon.setDataSources`](#setdatasources).
    </ParamField>

    **Example:**

    ```javascript icon="js" FieldMapper input expandable theme={null}
    const config = paragon.getIntegrationConfig("salesforce");
    const input = config.availableUserSettings[0];
    // { id: "...", type: "FIELD_MAPPER", title: "Map fields", sourceType: "customObjectMapping" }

    const sources = paragon.getSourcesForInput("salesforce", input);
    // { kind: "fieldMapper", recordSource: {...}, fieldSource: {...} }

    if (sources?.kind === "fieldMapper") {
      // Load record types
      const recordTypes = await paragon.getFieldOptions({
        integration: "salesforce",
        source: sources.recordSource,
      });

      // Load fields for a selected record type
      const fields = await paragon.getFieldOptions({
        integration: "salesforce",
        source: sources.fieldSource,
        parameters: [{
          key: sources.recordSource.cacheKey,
          source: { type: "VALUE", value: "Task" },
        }],
      });
    }
    ```
  </Tab>

  <Tab title="ComboSources">
    Returned for [`ComboInput`](/connect-portal/input-types-reference) input types (e.g. Combo Dropdown).

    <ParamField path="kind" type="const" required>
      `"combo"` for ComboSources.
    </ParamField>

    <ParamField path="mainInputSource" type="DynamicDataSource" required>
      The data source for the primary input. Pass to [`paragon.getFieldOptions`](#getfieldoptions) to load main options.
    </ParamField>

    <ParamField path="dependentInputSource" type="DynamicDataSource" required>
      The data source for the dependent input. Pass to [`paragon.getFieldOptions`](#getfieldoptions) with `parameters` for the user's main selection.
    </ParamField>

    **Example:**

    ```javascript icon="js" ComboInput expandable theme={null}
    const config = paragon.getIntegrationConfig("jira");
    const input = config.availableUserSettings[0];
    // { id: "...", type: "COMBO_INPUT", sourceType: "projectIssueStatusTypeCombo" }

    const sources = paragon.getSourcesForInput("jira", input);
    // { kind: "combo", mainInputSource: {...}, dependentInputSource: {...} }

    if (sources?.kind === "combo") {
      // Load main options (e.g. Projects)
      const projects = await paragon.getFieldOptions({
        integration: "jira",
        source: sources.mainInputSource,
      });

      // Load dependent options (e.g. Issue Statuses for a selected Project)
      const statuses = await paragon.getFieldOptions({
        integration: "jira",
        source: sources.dependentInputSource,
        parameters: [{
          key: sources.mainInputSource.cacheKey,
          source: { type: "VALUE", value: "PROJECT-1" },
        }],
      });
    }
    ```
  </Tab>

  <Tab title="DefaultFieldValueSources">
    Returned for [`DynamicComboInput`](/connect-portal/input-types-reference) input types.

    <ParamField path="kind" type="const" required>
      `"defaultFieldValue"` for DefaultFieldValueSources.
    </ParamField>

    <ParamField path="mainInputSource" type="DynamicDataSource" required>
      The data source for the primary input. Pass to [`paragon.getFieldOptions`](#getfieldoptions) to load main options.
    </ParamField>

    <ParamField path="dependentInputSource" type="DynamicDataSource" required>
      The data source for the dependent input. Pass to [`paragon.getFieldOptions`](#getfieldoptions) with `parameters` for the user's main selection.
    </ParamField>

    <ParamField path="variableInputSource" type="DynamicDataSource">
      An optional data source for a variable input.
    </ParamField>

    **Example:**

    ```javascript icon="js" DynamicComboInput expandable theme={null}
    const config = paragon.getIntegrationConfig("salesforce");
    const input = config.availableUserSettings[0];
    // { id: "...", type: "DYNAMIC_COMBO_INPUT", sourceType: "dynamicComboAction" }

    const sources = paragon.getSourcesForInput("salesforce", input);
    // { kind: "defaultFieldValue", mainInputSource: {...}, dependentInputSource: {...}, variableInputSource: {...} }

    if (sources?.kind === "defaultFieldValue") {
      const mainOptions = await paragon.getFieldOptions({
        integration: "salesforce",
        source: sources.mainInputSource,
      });

      const dependentOptions = await paragon.getFieldOptions({
        integration: "salesforce",
        source: sources.dependentInputSource,
        parameters: [{
          key: sources.mainInputSource.cacheKey,
          source: { type: "VALUE", value: mainOptions.data[0].value },
        }],
      });
    }
    ```
  </Tab>
</Tabs>

***

### .setDataSources

Call `paragon.setDataSources` to register custom data sources for dropdown and field mapping inputs when using the [Headless Connect Portal](/connect-portal/headless-connect-portal). This can be used in place of passing `dropdowns` and `mapObjectFields` inline with `paragon.connect`, for Headless Connect Portal implementations.

Data sources can be registered globally (applied to all integrations) or for specific integrations. When an integration-specific source exists, it takes priority over a global source with the same key.

This function should be called once after [`paragon.setHeadless`](#setheadless) and before rendering any inputs.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    paragon.setDataSources(config);
    ```
  </Tab>
</Tabs>

**Arguments:**

<ParamField path="config" type="SetDataSourcesConfig" required>
  <Expandable title="child properties" defaultOpen>
    <ParamField path="dropdowns" type="Record<string, CustomDropdownField[] | CustomDropdownOptions>">
      Global custom dropdown data sources, keyed by the dropdown `key` identifier. Values can be either a static array of `CustomDropdownField[]` options (objects with `label` and `value` strings), or a `CustomDropdownOptions` object for dynamic loading:

      ```javascript icon="js" Static dropdown options theme={null}
      paragon.setDataSources({
        dropdowns: {
          my_custom_dropdown: [
            { label: "Option A", value: "a" },
            { label: "Option B", value: "b" },
          ],
        },
      });
      ```

      <Expandable title="child properties (CustomDropdownOptions)">
        <ParamField path="loadOptions" type="(cursor?: string, search?: string) => Promise<{ options: CustomDropdownField[], nextPageCursor: string | null }>" required>
          A function that returns dropdown options with support for pagination and search. Called by the SDK when options need to be loaded or refreshed.
        </ParamField>

        <ParamField path="refreshOnOpen" type="boolean">
          If `true`, the dropdown options will be reloaded every time the dropdown is opened. Useful for dependent dropdowns where options depend on other input values. Defaults to `false`.
        </ParamField>

        ```javascript icon="js" Dynamic dropdown with loader expandable theme={null}
        paragon.setDataSources({
          dropdowns: {
            my_dynamic_dropdown: {
              loadOptions: async (cursor, search) => {
                const response = await fetch(`/api/options?cursor=${cursor}&search=${search}`);
                const data = await response.json();
                return {
                  options: data.items,
                  nextPageCursor: data.nextCursor,
                };
              },
            },
          },
        });
        ```
      </Expandable>
    </ParamField>

    <ParamField path="mapObjectFields" type="Record<string, DynamicMappingField[] | DynamicMappingOptions | DynamicFieldMappingConfig>">
      Global field mapping data sources, keyed by field mapping name. Values can be one of the following:

      <Expandable title="child properties (DynamicMappingField)">
        **Option 1: `DynamicMappingField[]`** - Static array of mapping options.

        <ParamField path="label" type="string" required>
          The display label for the field.
        </ParamField>

        <ParamField path="value" type="string" required>
          The value identifier for the field.
        </ParamField>
      </Expandable>

      <Expandable title="child properties (DynamicMappingOptions)">
        **Option 2: `DynamicMappingOptions`** — Configurable mapping behavior with static fields.

        <ParamField path="fields" type="DynamicMappingField[]" required>
          The list of available fields (objects with `label` and `value` strings).
        </ParamField>

        <ParamField path="defaultFields" type="string[]">
          Field values that should be selected by default.
        </ParamField>

        <ParamField path="userCanRemoveMappings" type="boolean">
          Whether users can remove field mappings.
        </ParamField>

        <ParamField path="userCanCreateFields" type="boolean">
          Whether users can create new fields.
        </ParamField>
      </Expandable>

      <Expandable title="child properties (DynamicFieldMappingConfig)">
        **Option 3: `DynamicFieldMappingConfig`** — Fully dynamic field mapping with loader functions for fetching object types and fields at runtime.

        <ParamField path="objectTypes.get" type="(cursor?: string, search?: string) => Promise<{ options: { label: string, value: string }[], nextPageCursor: string | null }>" required>
          A loader function to fetch available object types with pagination and search support.
        </ParamField>

        <ParamField path="integrationFields.get" type="(params: { objectType: string }, cursor?: string, search?: string) => Promise<{ options: { label: string, value: string }[], nextPageCursor: string | null }>" required>
          A loader function to fetch available fields for a given object type with pagination and search support.
        </ParamField>

        <ParamField path="applicationFields" type="object">
          Optional configuration for application-side fields.

          <Expandable title="child properties">
            <ParamField path="fields" type="{ label: string, value: string }[]" required>
              The list of application fields available for mapping.
            </ParamField>

            <ParamField path="defaultFields" type="string[]">
              Field values that should be selected by default.
            </ParamField>

            <ParamField path="userCanRemoveMappings" type="boolean">
              Whether users can remove field mappings.
            </ParamField>

            <ParamField path="userCanCreateFields" type="boolean">
              Whether users can create new fields.
            </ParamField>
          </Expandable>
        </ParamField>

        ```javascript icon="js" Field mapping with BYO loaders expandable theme={null}
        paragon.setDataSources({
          mapObjectFields: {
            myFieldMapping: {
              objectTypes: {
                get: async (cursor, search) => {
                  const response = await fetch(`/api/object-types?cursor=${cursor}&search=${search}`);
                  const data = await response.json();
                  return { options: data.items, nextPageCursor: data.nextCursor };
                },
              },
              integrationFields: {
                get: async ({ objectType }, cursor, search) => {
                  const response = await fetch(
                    `/api/fields?objectType=${objectType}&cursor=${cursor}&search=${search}`
                  );
                  const data = await response.json();
                  return { options: data.items, nextPageCursor: data.nextCursor };
                },
              },
              applicationFields: {
                fields: [
                  { label: "Name", value: "name" },
                  { label: "Email", value: "email" },
                ],
              },
            },
          },
        });
        ```
      </Expandable>
    </ParamField>

    <ParamField path="integrationSpecificSources" type="Record<string, { dropdowns?, mapObjectFields? }>">
      Integration-specific data sources that take priority over global sources. Keyed by integration type (e.g. `"salesforce"`), with the same `dropdowns` and `mapObjectFields` structure.

      ```javascript icon="js" Integration-specific sources expandable theme={null}
      paragon.setDataSources({
        dropdowns: {
          departments: [
            { label: "Engineering", value: "eng" },
            { label: "Sales", value: "sales" },
          ],
        },
        integrationSpecificSources: {
          salesforce: {
            dropdowns: {
              departments: [
                { label: "Engineering", value: "engineering" },
                { label: "Sales", value: "sales-dept" },
                { label: "Marketing", value: "marketing" },
              ],
            },
          },
        },
      });
      ```
    </ParamField>
  </Expandable>
</ParamField>

***

### .enableWorkflow

Call `paragon.enableWorkflow` to turn on a workflow for a user by ID.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript  theme={null}
    paragon.enableWorkflow(workflowId);
    ```

    **Arguments:**

    <ParamField path="workflowId" type="string" required>
      Workflow ID
    </ParamField>
  </Tab>

  <Tab title="REST API" icon="terminal">
    ```http icon="terminal" HTTP theme={null}
    POST https://api.useparagon.com/projects/PROJECT_ID/sdk/workflows/WORKFLOW_ID

    Authorization: Bearer PARAGON_USER_TOKEN
    ```

    **Arguments:**

    <ParamField path="PROJECT_ID" type="string" required>
      You can find your project ID in the Overview tab of any Integration
    </ParamField>

    <ParamField path="WORKFLOW_ID" type="string" required>
      Workflow ID
    </ParamField>

    <ParamField path="PARAGON_USER_TOKEN" type="string" required>
      See [Setup](/getting-started/installing-the-connect-sdk) for how to encode your user token
    </ParamField>
  </Tab>
</Tabs>

***

### .disableWorkflow

Call `paragon.disableWorkflow` to turn off a workflow for a user by ID.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript  theme={null}
    paragon.disableWorkflow(workflowId);
    ```

    **Arguments:**

    <ParamField path="workflowId" type="string" required>
      Workflow ID
    </ParamField>
  </Tab>

  <Tab title="REST API" icon="terminal">
    ```http icon="terminal" HTTP theme={null}
    DELETE https://api.useparagon.com/projects/PROJECT_ID/sdk/workflows/WORKFLOW_ID

    Authorization: Bearer PARAGON_USER_TOKEN
    ```

    **Arguments:**

    <ParamField path="PROJECT_ID" type="string" required>
      You can find your project ID in the Overview tab of any Integration
    </ParamField>

    <ParamField path="WORKFLOW_ID" type="string" required>
      Workflow ID
    </ParamField>

    <ParamField path="PARAGON_USER_TOKEN" type="string" required>
      See [Setup](/getting-started/installing-the-connect-sdk) for how to encode your user token
    </ParamField>
  </Tab>
</Tabs>

***

### .updateWorkflowState

Call `paragon.updateWorkflowState` to enable or disable workflows for a user.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    paragon.updateWorkflowState(workflowStateUpdate, options);
    ```
  </Tab>
</Tabs>

**Arguments:**

<ParamField path="workflowStateUpdate" type="object" required>
  A partial update object where keys are workflow IDs and values are `true` or `false`. Any workflow IDs not included in this object will not be updated in this call.

  ```javascript icon="js" on Example theme={null}
  {
    "bb89897b-ec2a-4118-b091-c12713c6bffa": true,
    "487c67e1-bc3f-406e-acc4-085f897dc564": false,
  }
  ```
</ParamField>

<ParamField path="options" type="CredentialConfigOptions | undefined">
  Optionally specify a Credential and Configuration to target, if using [Multi-Account Authorization](/apis/api-reference/multi-account-authorization) or [Multi-Configuration](/apis/api-reference/multi-configuration).

  <Accordion title="Show child properties">
    <ParamField path="selectedCredentialId" type="string">
      The Credential ID (a UUID) of the connected account you want to update, if using [Multi-Account Authorization](/apis/api-reference/multi-account-authorization).
    </ParamField>

    <ParamField path="selectedConfigurationId" type="string">
      The Configuration ID (a UUID or an External ID prefixed with `ext:`), if using [Multi-Configuration](/apis/api-reference/multi-configuration).
    </ParamField>
  </Accordion>
</ParamField>

***

### .updateWorkflowUserSettings

Call `paragon.updateWorkflowUserSettings` to update any workflow-level [User Settings](/connect-portal/workflow-user-settings) for your Connected User.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    paragon.updateWorkflowUserSettings(integrationType, workflowId, userSettingsUpdate, options);
    ```
  </Tab>
</Tabs>

**Arguments:**

<ParamField path="integrationType" type="string" required>
  An integration type string, like `salesforce`.
</ParamField>

<ParamField path="workflowId" type="string" required>
  The ID of the Workflow that the workflow-level User Setting you are modifying belongs to. If you are trying to modify an integration-level User Setting, call [`paragon.updateIntegrationUserSettings`](#updateintegrationusersettings) instead.
</ParamField>

<ParamField path="userSettingsUpdate" type="object" required>
  A partial update object where the keys are the `id` properties of User Settings objects (which you can get from [`paragon.getIntegrationConfig`](#getintegrationconfig)) and the values are the user's selection for the matching input type.

  Any keys that are not included in the object will not be updated.

  The type for each value will depend on the input type. See [Input Types Reference](/connect-portal/input-types-reference) to see the value type for each input.

  ```json Example theme={null}
  {
    "1f7474a5-8b8e-4c25-8d44-29f20aec3fe4": "general"
  }
  ```
</ParamField>

<ParamField path="options" type="CredentialConfigOptions | undefined">
  Optionally specify a Credential and Configuration to target, if using [Multi-Account Authorization](/apis/api-reference/multi-account-authorization) or [Multi-Configuration](/apis/api-reference/multi-configuration).

  <Accordion title="Show child properties">
    <ParamField path="selectedCredentialId" type="string">
      The Credential ID (a UUID) of the connected account you want to update, if using [Multi-Account Authorization](/apis/api-reference/multi-account-authorization).
    </ParamField>

    <ParamField path="selectedConfigurationId" type="string">
      The Configuration ID (a UUID or an External ID prefixed with `ext:`), if using [Multi-Configuration](/apis/api-reference/multi-configuration).
    </ParamField>
  </Accordion>
</ParamField>

***

### .getCustomWebhookUserManualUrl

If you are using [Custom Webhooks](/resources/custom-webhooks) with a User-Level URL and [Manual Setup](/resources/custom-webhooks#option-2%3A-manual-setup), you can use `paragon.getCustomWebhookUserManualUrl` to construct the user-specific URL that must be registered by your customer in the integration to complete webhook setup.

There is no API endpoint available for this method. However, you can construct the user-specific URL without the JavaScript SDK as described in the [Custom Webhooks docs](/resources/custom-webhooks#user-specific-webhook-target-urls).

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    // Present this value to your user to register this webhook in their account manually
    const webhookUrl = paragon.getCustomWebhookUserManualUrl(workflowId, credentialId);
    ```
  </Tab>
</Tabs>

**Arguments:**

<ParamField path="workflowId" type="string" required>
  The ID of a Workflow that utilizes this Custom Webhook. If the same Custom Webhook is used in multiple Workflows, any one of these workflows can be used as `workflowId`.
</ParamField>

<ParamField path="credentialId" type="string">
  If you are using [Multi-Account Authorization](/apis/api-reference/multi-account-authorization) and there may be more than one account connected for a given integration, pass the `credentialId` to ensure that received events are routed to the correct account.
</ParamField>

***

### .workflow

Call `paragon.workflow` to trigger a Paragon workflow that sends a custom response back to your app. Note: The workflow must be enabled and use a Request-type trigger.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    await paragon.workflow(workflowId, options);
    ```

    **Arguments:**

    <ParamField path="workflowId" type="string" required>
      The ID of the workflow to trigger.
    </ParamField>

    <ParamField path="options" type="FetchOptions">
      <Expandable title="Optional FetchOptions">
        <ParamField body="body" type="object">
          The request body to pass to the workflow trigger.
        </ParamField>
      </Expandable>
    </ParamField>

    **Example:**

    ```javascript icon="js" theme={null}
    paragon.authenticate(PROJECT_ID, PARAGON_USER_TOKEN);

    await paragon.workflow(WORKFLOW_ID, {
      "body": {
        "email": "bowie@useparagon.com",
        "first_name": "Bowie",
        "last_name": "Foo"
      }
    });
    ```
  </Tab>

  <Tab title="REST API" icon="terminal">
    ```http icon="terminal" HTTP theme={null}
    POST https://api.useparagon.com/projects/PROJECT_ID/sdk/triggers/WORKFLOW_ID

    Authorization: Bearer PARAGON_USER_TOKEN
    Content-Type: application/json

    {
      ...options
    }
    ```

    **Arguments:**

    <ParamField path="PROJECT_ID" type="string" required>
      You can find your project ID in the Overview tab of any Integration
    </ParamField>

    <ParamField path="WORKFLOW_ID" type="string" required>
      The ID of the workflow to trigger.
    </ParamField>

    <ParamField path="PARAGON_USER_TOKEN" type="string" required>
      See [Setup](/getting-started/installing-the-connect-sdk) for how to encode your user token
    </ParamField>

    <ParamField path="options" type="FetchOptions">
      <Expandable title="Optional FetchOptions">
        <ParamField body="body" type="object">
          The request body to pass to the workflow trigger.
        </ParamField>
      </Expandable>
    </ParamField>

    **Example:**

    ```http icon="terminal" HTTP theme={null}
    POST https://api.useparagon.com/projects/PROJECT_ID/sdk/triggers/WORKFLOW_ID

    Authorization: Bearer PARAGON_USER_TOKEN
    Content-Type: application/json

    {
      "email": "bowie@useparagon.com",
      "first_name": "Bowie",
      "last_name": "Foo"
    }
    ```
  </Tab>
</Tabs>

***

### .request

Call `paragon.request` to send an API request to a third-party integration on behalf of one of your users.

Every integration in your dashboard has a code example of using `paragon.request`.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    await paragon.request(integrationType, path, requestOptions);
    ```
  </Tab>
</Tabs>

**Arguments:**

<ParamField path="integrationType" type="string" required>
  The short name for the integration (i.e. "salesforce" or "googleCalendar"). You can find this string on the Overview tab of the integration you want to access, on your Paragon dashboard.
</ParamField>

<ParamField path="path" type="string" required>
  The path (without the hostname) of the API request you are trying to access. An example might be: "/v1/charges" for Stripe's charge API or "chat.postMessage" for Slack's Web API.
</ParamField>

<ParamField path="requestOptions" type="object">
  Optional request options to include:

  <Expandable title="child properties">
    <ParamField path="body" type="object">
      An object representing JSON contents of the request.
    </ParamField>

    <ParamField path="method" type="string">
      An HTTP verb such as "GET" or "POST". Defaults to GET.
    </ParamField>

    <ParamField path="headers" type="object">
      Additional HTTP headers to include in the request.
    </ParamField>
  </Expandable>

  If `requestOptions` is omitted, the SDK issues a `GET` request without a body.
</ParamField>

The function returns a promise for the request output, which will have a shape that varies depending on the integration and API endpoint.

**Examples:**

<CodeGroup>
  ```typescript JavaScript SDK theme={null}
  await paragon.request('slack', '/chat.postMessage', {
  	method: 'POST',
  	body: {
  		channel: 'CXXXXXXX0' // Channel ID,
  		text: 'This message was sent with Paragon Connect :exploding_head:'
  	}
  });

  // -> Responds with { ok: true }, and sends a message :)
  ```

  ```http icon="terminal" HTTP theme={null}
  POST https://proxy.useparagon.com/projects/<Paragon Project ID>/sdk/proxy/slack/chat.postMessage

  Authorization: Bearer <Paragon User Token>
  Content-Type: application/json

  {
      "channel": "CXXXXXXX0",
      "text": "This message was sent with Paragon Connect :exploding_head:"
  }

  // -> Responds with { output: { ok: true }}, and sends a message :)
  ```
</CodeGroup>

***

### .event

App Events can be sent from your application using the Paragon SDK or REST API. In both cases, you must pass two parameters:

* **name** - the event name defined in your App Event

* **payload** - the event payload that should match the event schema defined in your App Event

See the code examples below for how to send App Events using the Paragon SDK or API.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    var eventName = "Contact Created";
    var eventPayload = { "name": "Brandon", "email": "b@useparagon.com" };

    paragon.event(eventName, payload);
    ```

    **Arguments:**

    <ParamField path="eventName" type="string" required>
      The event name defined in your App Event
    </ParamField>

    <ParamField path="payload" type="object" required>
      The event payload that should match the event schema defined in your App Event
    </ParamField>
  </Tab>

  <Tab title="REST API" icon="terminal">
    ```http icon="terminal" HTTP theme={null}
    POST https://api.useparagon.com/projects/PROJECT_ID/sdk/events/trigger

    Authorization: Bearer PARAGON_USER_TOKEN
    Content-Type: application/json

    {
        "name": "Contact Created",
        "payload": {
            "name": "Brandon",
            "email": "b@useparagon.com"
        }
    }
    ```

    **Arguments:**

    <ParamField path="PROJECT_ID" type="string" required>
      You can find your project ID in the Overview tab of any Integration
    </ParamField>

    <ParamField path="PARAGON_USER_TOKEN" type="string" required>
      See [Setup](/getting-started/installing-the-connect-sdk) for how to encode your user token
    </ParamField>

    <ParamField path="name" type="string" required>
      The event name defined in your App Event
    </ParamField>

    <ParamField path="payload" type="object" required>
      The event payload that should match the event schema defined in your App Event
    </ParamField>
  </Tab>
</Tabs>

When sending live events from your application, Paragon will not validate that your event payload matches the defined event schema.

***

### .setHeadless

Call `paragon.setHeadless` to enable or disable Headless mode for the SDK. When headless mode is enabled, the SDK will not render the Connect Portal UI and will instead expose functions for you to build your own UI.

```javascript icon="js" JavaScript theme={null}
paragon.setHeadless(true);
```

This should be called once after SDK initialization. See the [Headless Connect Portal](/connect-portal/headless-connect-portal) guide for more details.

***

## API Only

### `GET` project's integrations

Returns a list of the integrations enabled for the Paragon project by the ID in the URL.

* Includes the Connect Portal configuration for each integration (as `.configs`) and the Workflows associated with each integration (as `.workflows`)

You can use [`paragon.getIntegrationMetadata`](#getintegrationmetadata) and [`paragon.getIntegrationConfig`](#getintegrationconfig) when using the JavaScript SDK.

```http icon="terminal" HTTP expandable theme={null}
GET https://api.useparagon.com/projects/PROJECT_ID/sdk/integrations

Authorization: Bearer PARAGON_USER_TOKEN
Content-Type: application/json

// Example response (may include more than is in this list):

[{
  "id": "2f08e65f-d924-42ab-9618-b6023d82ffbd",
  "projectId": "908f4c5e-6394-46a5-9355-3f729edbd160",
  "customIntegrationId": null,
  "type": "slack",
  "isActive": true,
  "configs": [
    {
      "id": "3ebcc179-a1a6-447f-8dc9-5017f40f08ef",
      "values": {
        "overview": "####Our Slack integration enables you to:\n   \n\n• Receive alerts and notifications in your Slack workspace\n• Notify or DM specific team members based on certain activity",
        "sharedMeta": {},
        "accentColor": "#4A154B",
        "description": "Send notifications to Slack",
        "workflowMeta": {}
      }
    },
  ],
  "workflows": [
    {
      "id": "1b22193b-e355-458d-b6a3-5e5516edb588",
      "description": "Send Updates to Slack",
      "projectId": "908f4c5e-6394-46a5-9355-3f729edbd160",
      "integrationId": "2f08e65f-d924-42ab-9618-b6023d82ffbd",
      "steps": []
    }
  ],
  "customIntegration": null,
  "hasCredential": true,
  "connectedUserLimitOnDevCred": 0,
  "connectedUserLimitReached": true,
  "name": "Slack",
  "brandColor": "#4A154B",
  "needPreOauthInputs": false,
  "providerType": "slack",
  "authenticationType": "oauth"
}]
```

**Arguments:**

<ParamField path="PROJECT_ID" type="string" required>
  You can find your project ID in the Overview tab of any Integration
</ParamField>

<ParamField path="PARAGON_USER_TOKEN" type="string" required>
  See [Setup](/getting-started/installing-the-connect-sdk) for how to encode your user token
</ParamField>

### `GET` user's Connect credentials

Returns a list of the user's Connect credentials (i.e., the accounts connected and authorized by the end user).

* The **providerId** is the authenticated user's ID assigned by their integration provider (e.g. for a Salesforce integration, this would be the user's Salesforce user ID)

This method is currently available via REST API only.

```http icon="terminal" HTTP theme={null}
GET https://api.useparagon.com/projects/PROJECT_ID/sdk/credentials

Authorization: Bearer PARAGON_USER_TOKEN
Content-Type: application/json

// Example response (may include more than is in this list):

[{
  "id": "00da4146-7ac4-4253-a8f7-96849b8137d9",
  "dateCreated": "2021-03-24T12:19:21.511Z",
  "dateUpdated": "2021-03-24T12:19:28.512Z",
  "dateDeleted": null,
  "projectId": "db06d291-ba2c-41c5-9a12-9362abfd6228",
  "integrationId": "95bedc9f-6a22-4855-b08d-e68dc073ad91",
  "personaId": "0563109f-5e71-46c5-8483-1ac8c0913d6c",
  "config": {
    "configuredWorkflows": {
      "3eb95154-3c7b-413c-bf14-ba367d95b53f": {
        "enabled": true,
        "settings": {
					"example-input-id": "example value"
				}
      }
    }
  },
  "isPreviewCredential": false,
  "providerId": "50150244515"
}]
```

**Arguments:**

<ParamField path="PROJECT_ID" type="string" required>
  You can find your project ID in the Overview tab of any Integration
</ParamField>

<ParamField path="PARAGON_USER_TOKEN" type="string" required>
  See [Setup](/getting-started/installing-the-connect-sdk) for how to encode your user token
</ParamField>

### `UPDATE` user's Connect credential

Updates the user's connected integration account, including any settings and configured workflows.

This endpoint updates by replacement with respect to the `config` property, so this endpoint should only be used after retrieving the existing value (which can be done by using the above endpoint: [Get user's Connect credentials](/apis/api-reference#get-users-connect-credentials)).

Alternatively, you can use the SDK to update User Settings or workflow enablements:

* [`paragon.updateIntegrationUserSettings`](/apis/api-reference#updateintegrationusersettings): Update integration-level User Settings.
* [`paragon.updateWorkflowUserSettings`](/apis/api-reference#updateworkflowusersettings): Update workflow-level User Settings.
* [`paragon.updateWorkflowState`](/apis/api-reference#updateworkflowstate): Update workflow enablements.

```http icon="terminal" HTTP theme={null}
PATCH https://api.useparagon.com/projects/PROJECT_ID/sdk/credentials/CREDENTIAL_ID

Authorization: Bearer <Paragon User Token>
Content-Type: application/json

// Body: Example showing WORKFLOW_ID being enabled
{
    "config": {
        "configuredWorkflows": {
            ...
            WORKFLOW_ID: {
                "enabled": true,
                "settings": {}
            }
        },
        "sharedSettings": {...}
    }
}
```

**Arguments:**

<ParamField path="PROJECT_ID" type="string" required>
  You can find your project ID in the Overview tab of any Integration
</ParamField>

<ParamField path="CREDENTIAL_ID" type="string" required>
  The ID of the Connect credential to update. Retrieve it from the [`/sdk/credentials`](/apis/api-reference#get-users-connect-credentials) endpoint.
</ParamField>

<ParamField path="PARAGON_USER_TOKEN" type="string" required>
  See [Setup](/getting-started/installing-the-connect-sdk) for how to encode your user token
</ParamField>

<ParamField path="config" type="object" required>
  The configuration object to update. This will replace the existing `config` property entirely, so you must provide the full existing value with your intended changes applied.
</ParamField>

**Note**: In the above example, the existing value for `config` must be provided in full, with the intended changes applied. This is because `config` will be updated by replacement.

## Headless Connect installFlow

Use `paragon.installFlow` when implementing the [Headless Connect Portal](/connect-portal/headless-connect-portal) to guide your user through the installation process for an integration.

**InstallFlowStage:**

These are the possible install flow stages received in the `onNext` callback of `InstallFlow` that should be rendered by your app to guide the user through the installation process.

<Tabs>
  <Tab title="AccountTypeStage">
    In the `AccountTypeStage`, the user should be prompted with a list of account types that they can choose from.

    If you want to skip this stage, pass the first account type option (or `"default"`) to `paragon.installFlow.setAccountType` to move to the next stage.

    ```javascript icon="js" Example (Salesforce) theme={null}
    {
      "stage": "accountType",
      "options": [
        { "id": "default", "accountDescription": "Production Account" },
        { "id": "sandbox", "accountDescription": "Sandbox Account"}
      ]
    }
    ```

    <ParamField path="stage" type="const">
      `"accountType"` for AccountTypeStage.
    </ParamField>

    <ParamField path="options" type="AccountType[]">
      The list of account types that the user can choose from.

      <Expandable title="child properties">
        <ParamField path="id" type="string" required>
          The ID of the account type. Pass this to `paragon.installFlow.setAccountType` when the user selects an option.
        </ParamField>

        <ParamField path="accountDescription" type="string">
          The human-readable description of the account type.
        </ParamField>
      </Expandable>
    </ParamField>
  </Tab>

  <Tab title="PreOptionsStage">
    In the `PreOptionsStage`, the user should be prompted with inputs to collect the necessary details for API key authorization or for the next OAuth stage in the flow.

    ```javascript icon="js" Example (Shopify) theme={null}
    {
      "stage": "preOptions",
      "options": [
        {
          "id": "SHOP_NAME",
          "title": "Enter your Shopify username",
          "subtitle": "Enter your Shopify username, e.g. https://<username>.myshopify.com.",
          "placeholder": "username",
          "type": "TEXT_NO_VARS"
        }
      ]
    }
    ```

    <ParamField path="stage" type="const">
      `"preOptions"` for PreOptionsStage.
    </ParamField>

    <ParamField path="options" type="InputType[]">
      The list of inputs to prompt the user with in this stage. You can see a full list of input types that are used by the Connect Portal and must be rendered by your implementation in [Input Types Reference](/connect-portal/input-types-reference).

      <Expandable title="child properties">
        <ParamField path="id" type="string" required>
          Use the input `id` as the key of the object you pass to [`paragon.setPreOptions`](#installflowsetpreoptions). The value will be the input provided by the user.
        </ParamField>

        <ParamField path="type" type="enum" required>
          The type of this input, which will be one of the inputs in [Input Types Reference](/connect-portal/input-types-reference).
        </ParamField>

        <ParamField path="title" type="string" required>
          The title to display to the user to describe this input.
        </ParamField>

        <ParamField path="subtitle" type="string">
          The descriptive text to display to the user to further describe or provide context to this input.
        </ParamField>

        <ParamField path="placeholder" type="string">
          The placeholder or example value to display to the user.
        </ParamField>
      </Expandable>
    </ParamField>
  </Tab>

  <Tab title="PostOptionsStage">
    In the `PostOptionsStage`, the user should be prompted with inputs to finalize their account setup after the OAuth flow.

    ```javascript icon="js" Example (Jira) theme={null}
    {
      "stage": "postOptions",
      "credentialId": "987654-56a7-89b1-cd23-456789abcdef",
      "options": [
        {
          "id": "JIRA_CLOUD_ID",
          "type": "DYNAMIC_ENUM",
          "title": "Choose a Jira site to connect.",
          "subtitle": "The Jira site, where all operations will be performed.",
          "sourceType": "getAvailableSites",
          "required": true
        }
      ],
      "done": false
    }
    ```

    <ParamField path="stage" type="const">
      `"postOptions"` for PostOptionsStage.
    </ParamField>

    <ParamField path="credentialId" type="string">
      The ID of the credential that was created during the OAuth flow. Available once the credential has been created, so you can pass it to [`paragon.getFieldOptions`](#getfieldoptions) when loading options for dynamic inputs in this stage.
    </ParamField>

    <ParamField path="options" type="InputType[]">
      The list of inputs to prompt the user with in this stage. You can see a full list of input types that are used by the Connect Portal and must be rendered by your implementation in [Input Types Reference](/connect-portal/input-types-reference).

      <Expandable title="child properties">
        <ParamField path="id" type="string" required>
          Use the input `id` as the key of the object you pass to [`paragon.setPostOptions`](#installflowsetpostoptions). The value will be the input provided by the user.
        </ParamField>

        <ParamField path="type" type="enum" required>
          The type of this input, which will be one of the inputs in [Input Types Reference](/connect-portal/input-types-reference).
        </ParamField>

        <ParamField path="title" type="string" required>
          The title to display to the user to describe this input.
        </ParamField>

        <ParamField path="subtitle" type="string">
          The descriptive text to display to the user to further describe or provide context to this input.
        </ParamField>

        <ParamField path="placeholder" type="string">
          The placeholder or example value to display to the user.
        </ParamField>

        <ParamField path="sourceType" type="string">
          The source type of this input, defined for dynamic enum inputs. This value can be passed to [`paragon.getFieldOptions`](#getfieldoptions) to load the options for the input.

          See a walkthrough of implementing dynamic input types in [Exposing User Settings](/connect-portal/headless-connect-portal#exposing-user-settings).
        </ParamField>

        <ParamField path="required" type="boolean">
          Whether this input is required.
        </ParamField>
      </Expandable>
    </ParamField>
  </Tab>

  <Tab title="InstructionStage">
    In the `InstructionStage`, the user should be shown instructional content with call-to-action buttons and a finish button to proceed to the next stage.

    ```javascript icon="js" Example (Salesforce) theme={null}
    {
      "stage": "instruction",
      "content": "## Install Package\n\nPlease install the package using the link below.\n\n![Install Image](https://cdn.useparagon.com/image.png \"Install Image\")\n\nAfter installation, click the finish button.",
      "ctas": [
        {
          "type": "link",
          "label": "Install Package",
          "href": "https://example.com/package-install"
        },
        {
          "type": "copyButton",
          "label": "Copy link",
          "copyText": "https://example.com/package-install"
        }
      ],
      "finish": {
        "type": "finishButton",
        "label": "I've installed the package",
        "onClick": Function
      },
      "done": false
    }
    ```

    <ParamField path="stage" type="const">
      `"instruction"` for InstructionStage.
    </ParamField>

    <ParamField path="content" type="string" required>
      Markdown-formatted content to display to the user. This can include headings, images, and other markdown elements.
    </ParamField>

    <ParamField path="ctas" type="CTA[]">
      An array of call-to-action buttons to display alongside the content. Each CTA can be either a link or a copy button.

      <Expandable title="child properties">
        <Tabs>
          <Tab title="Link">
            <ParamField path="type" type="const" required>
              `"link"` for Link CTAs.
            </ParamField>

            <ParamField path="label" type="string" required>
              The text to display on the link button.
            </ParamField>

            <ParamField path="href" type="string" required>
              The URL to navigate to when the link is clicked.
            </ParamField>
          </Tab>

          <Tab title="CopyButton">
            <ParamField path="type" type="const" required>
              `"copyButton"` for CopyButton CTAs.
            </ParamField>

            <ParamField path="label" type="string" required>
              The text to display on the copy button.
            </ParamField>

            <ParamField path="copyText" type="string" required>
              The text to copy to the clipboard when the button is clicked.
            </ParamField>
          </Tab>
        </Tabs>
      </Expandable>
    </ParamField>

    <ParamField path="finish" type="FinishButton" required>
      The finish button that the user clicks to proceed to the next stage after completing the instructions.

      <Expandable title="child properties">
        <ParamField path="type" type="const" required>
          `"finishButton"` for FinishButton.
        </ParamField>

        <ParamField path="label" type="string" required>
          The text to display on the finish button.
        </ParamField>

        <ParamField path="onClick" type="function" required>
          The callback function provided by the SDK to execute when the finish button is clicked. When this button is clicked, call `finish.onClick()` to mark the instruction stage as complete.
        </ParamField>
      </Expandable>
    </ParamField>
  </Tab>
</Tabs>

***

### .installFlow\.start

Call `paragon.installFlow.start` to begin an install flow for an integration. [See an example call](/connect-portal/headless-connect-portal#example-install-flow).

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    paragon.installFlow.start(integrationType, options);
    ```
  </Tab>
</Tabs>

**Arguments:**

<ParamField path="integrationType" type="string" required>
  The integration type string, like `salesforce`.
</ParamField>

<ParamField path="options" type="object" required>
  <Expandable title="child properties" defaultOpen>
    <ParamField path="onNext(nextStage)" type="function">
      This callback is called when the install flow is ready to move to the next stage.

      Your app must render the appropriate UI for each stage, so that your user can provide the necessary details in that stage to connect their account.

      <Expandable title="callback arguments">
        <ParamField path="nextStage" type="InstallFlowStage">
          The install flow stage for your app to render. See [InstallFlowStage](#installflowstage) for more details.
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField path="onComplete()" type="function">
      This callback is called when the install flow completes successfully.
    </ParamField>

    <ParamField path="onError(error, context)" type="function">
      This callback is called when the install flow fails, with an error object and error context.

      <Expandable title="callback arguments">
        <ParamField path="error" type="Error">
          The error object. You can read the `.name` of the error object to identify one of the following error types:

          * `OAuthBlockedError`: The browser blocked the OAuth prompt from appearing. This may require the user to allow popups in their browser settings.
          * `OAuthTimeoutError`: The OAuth prompt took longer than `oauthTimeout` milliseconds (as provided in `options`) to complete.
          * `UserNotAuthenticatedError`: The user is not authenticated with the Paragon SDK. Verify that `paragon.authenticate` has been called before starting the install flow.
          * `NoActiveInstallFlowError`: An install flow function was called, but no install flow is currently active. Call `paragon.installFlow.start` to start an install flow.
          * `HeadlessModeNotEnabledError`: Headless Connect Portal is not enabled. Call `paragon.setHeadless` to enable Headless mode.
          * `IntegrationNotFoundError`: The provided integration type is not found or has [not been enabled](/getting-started/displaying-the-connect-portal#activating-the-integration) in your Paragon project.
        </ParamField>

        <ParamField path="context" type="ErrorContext | null">
          The error context object.

          <Expandable title="child properties">
            <ParamField path="stage" type="InstallFlowStage">
              The stage that the install flow was on when the error occurred.

              **One of**: `accountType`, `preOptions`, `postOptions`, `instruction`.
            </ParamField>
          </Expandable>
        </ParamField>
      </Expandable>
    </ParamField>

    <ParamField path="oauthTimeout" type="number">
      The number of milliseconds to wait for an OAuth prompt to complete. If the user does not complete the OAuth prompt within this time, the install flow will fail, and the `onError` callback will be called.

      If not provided, there will be no timeout for the OAuth prompt.
    </ParamField>

    <ParamField path="allowMultipleCredentials" type="boolean">
      Set to `true` if using [Multi-Account Authorization](/apis/api-reference/multi-account-authorization). This will allow users to connect multiple accounts under one integration type.

      Defaults to `false`.
    </ParamField>

    <ParamField path="selectedCredentialId" type="string">
      Set this parameter to *replace* an account by a selected Credential ID instead of connecting a new account.

      This can be used to prompt a user to reconnect a credential if authorization has been revoked and the `status` of the credential is `INVALID`.
    </ParamField>

    <ParamField path="overrideRedirectUrl" type="string">
      Set this parameter to your Redirect Page URL for integrations like [Google Drive](/resources/integrations/google-drive#setting-up-a-redirect-page-in-your-app).
    </ParamField>
  </Expandable>
</ParamField>

***

### .installFlow\.setAccountType

Call `paragon.installFlow.setAccountType` when the user selects an account type in the `AccountTypeStage`.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    paragon.installFlow.setAccountType(accountType);
    ```
  </Tab>
</Tabs>

**Arguments:**

<ParamField path="accountType" type="string" required>
  The account type to set. This should be the `id` property of the Account Type option that the user selected.
</ParamField>

***

### .installFlow\.setPreOptions

Call `paragon.installFlow.setPreOptions` when the user finishes providing inputs in the `PreOptionsStage`.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    await paragon.installFlow.setPreOptions(values);
    ```
  </Tab>
</Tabs>

This returns a Promise that resolves when the values are saved. Upon success, the install flow will move to the next stage and call `onNext`. If there is no stage after the `PreOptionsStage`, the install flow will call `onComplete`.

**Arguments:**

<ParamField path="values" type="object" required>
  The values to set for the inputs in the `PreOptionsStage`.

  This should be an object, where the keys are `id`s of the inputs in the `PreOptionsStage`, and the values are the values that the user provided for each input.

  ```javascript icon="js" Example (Shopify) theme={null}
  {
    "SHOP_NAME": "my-shop"
  }
  ```
</ParamField>

***

### .installFlow\.setPostOptions

Call `paragon.installFlow.setPostOptions` when the user finishes providing inputs in the `PostOptionsStage`.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    await paragon.installFlow.setPostOptions(values);
    ```
  </Tab>
</Tabs>

This returns a Promise that resolves when the values are saved. Upon success, the install flow will be completed and call `onComplete`.

**Arguments:**

<ParamField path="values" type="object" required>
  The values to set for the inputs in the `PostOptionsStage`.

  This should be an object, where the keys are `id`s of the inputs in the `PostOptionsStage`, and the values are the values that the user provided for each input.

  ```javascript icon="js" Example (Jira) theme={null}
  {
    "JIRA_CLOUD_ID": "my-jira-cloud-id"
  }
  ```
</ParamField>

***

### .installFlow\.cancel

Call `paragon.installFlow.cancel` if your user abandons the integration connection process during an active install flow. This function resets the state for `paragon.installFlow` to begin again at another time.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    paragon.installFlow.cancel();
    ```
  </Tab>
</Tabs>

<Info>
  If your user has completed an OAuth connection but has *not* completed required post-OAuth options, this function will remove the credential with status `"PENDING"` automatically by calling `paragon.uninstallIntegration`.

  However, if the page has been refreshed or the SDK has been reloaded *since* the pending credential was connected, you will need to call `paragon.uninstallIntegration` manually to disconnect the pending credential from your user.
</Info>

***

## External File Picker

You can use the Paragon SDK to allow your user to select files from a File Storage integration in your app.

The SDK provides an `ExternalFilePicker` class to load any necessary JavaScript dependencies into your page and authenticate with your user's connected account.

**Supported integrations for ExternalFilePicker:**

* [Google Drive](/resources/integrations/google-drive#using-the-google-drive-file-picker)
* [OneDrive](/resources/integrations/onedrive#using-the-onedrive-file-picker)
* [SharePoint](/resources/integrations/sharepoint#using-the-sharepoint-file-picker)
* [Box](/resources/integrations/box#using-the-box-file-picker)

### .ExternalFilePicker

Construct a new instance of an ExternalFilePicker for an integration given by `integrationType`. Any required JS dependencies do not start loading until [`picker.init`](/apis/api-reference#pickerinit) is called.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    const picker = new paragon.ExternalFilePicker(integrationType, options);
    ```
  </Tab>
</Tabs>

**Arguments:**

<ParamField path="integrationType" type="string" required>
  Type of integration (i.e. "googledrive", "onedrive", "sharepoint", "box")
</ParamField>

<ParamField path="options" type="object">
  <Expandable title="Optional options">
    <ParamField body="allowedTypes" type="string[]">
      An array of MIME types to allow for file selection, e.g. `["application/pdf", "image/jpeg"]`. If `undefined`, all types will be allowed.
    </ParamField>

    <ParamField body="allowMultiSelect" type="boolean">
      If `true`, allow multiple files to be selected. Default: `false`.
    </ParamField>

    <ParamField body="allowFolderSelect" type="boolean">
      If `true`, allow folders to be selected. Default: `false`.
    </ParamField>

    <ParamField body="onOpen" type="function">
      Called when a Picker successfully appears in the app.
    </ParamField>

    <ParamField body="onClose" type="function">
      Called when a Picker gets closed.
    </ParamField>

    <ParamField body="onFileSelect" type="function">
      Called when a Picker file selection is made. `files` is an Array of objects with the selected file objects from the 3rd-party picker script.
    </ParamField>

    <ParamField body="onCancel" type="function">
      Called when a Picker gets closed without any files selected.
    </ParamField>
  </Expandable>
</ParamField>

**Example:**

```javascript icon="js" JavaScript theme={null}
const picker = new paragon.ExternalFilePicker("googledrive", {
  allowedTypes: ["application/pdf"],
  allowMultiSelect: false,
  onFileSelect(files) {
    console.log("User picked files", files);
  },
});
```

***

### picker.init

Initialize a file picker with required configuration `initConfig`. Required configuration varies per integration; see [integration-specific documentation](/apis/api-reference#supported-integrations-for-externalfilepicker) for specific details.

This function loads required JS dependencies into the page, if they have not already been loaded. Other methods, like `picker.open` and `picker.getInstance`, cannot be called until the Promise returned by `picker.init` is resolved.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    await picker.init(initConfig);
    ```
  </Tab>
</Tabs>

**Arguments:**

<ParamField path="initConfig" type="object" required>
  <Expandable title="child properties">
    <ParamField path="developerKey" type="string">
      The developer key required for certain integrations (e.g., Google Drive).
    </ParamField>

    <ParamField path="selectedCredentialId" type="string">
      Pass to select a specific account to pick files from when using [Multi-Account Authorization](/apis/api-reference/multi-account-authorization).
    </ParamField>
  </Expandable>
</ParamField>

**Example:**

```javascript icon="js" JavaScript theme={null}
await picker.init({
  developerKey: "AIzaS...",
});
```

***

### picker.open

Presents the file picker in your app.

Selected files or other events will be received in the [callbacks](/apis/api-reference#options) you specified in the constructor.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    picker.open();
    ```
  </Tab>
</Tabs>

***

### picker.getInstance

Returns a reference to the third-party JS library object that this file picker is using. This object can be used for additional integration-specific customization.

<Tabs>
  <Tab title="SDK" icon="js">
    ```javascript icon="js" JavaScript theme={null}
    const instance = picker.getInstance();
    ```
  </Tab>
</Tabs>
