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

# Integration Catalog

Build an integrations page that lets your tenants connect their apps. We recommend splitting it into two sections: **Connections** (accounts they've already connected) and **Integrations** (apps available to connect).

## Getting Started

1. Complete the [Quickstart: Product Integrations](/docs/getting-started/product-integrations) guide.
2. Ask your coding agent to build the integration catalog for your app:

> "Build an integrations page with two sections: 'Your Connections' showing connected accounts with disconnect, and 'Available Integrations' showing apps that can still be connected. Use the Membrane React SDK."

If you want to learn how it works under the hood — read on.

## React SDK

Install the React SDK and wrap your app with the provider.

```bash theme={null}
npm install @membranehq/react
```

```tsx theme={null}
import { MembraneProvider } from '@membranehq/react'

export function MyApp() {
  return (
    <MembraneProvider fetchToken={fetchToken}>
      <YourApp />
    </MembraneProvider>
  )
}
```

The `fetchToken` function should call your backend endpoint that generates [authentication tokens](/docs/how-membrane-works/authentication).

### Complete example

The key pattern: fetch both integrations and connections, then split integrations into "connected" and "available" based on whether a connection exists.

```tsx theme={null}
import { useIntegrations, useConnections, useMembrane } from '@membranehq/react'
import { useMemo } from 'react'

function IntegrationsPage() {
  const membrane = useMembrane()
  const { items: integrations, loading: integrationsLoading } = useIntegrations()
  const { items: connections, loading: connectionsLoading } = useConnections()

  // Split integrations into connected vs available
  const connectedIntegrationIds = useMemo(() => new Set(connections?.map((c) => c.integrationId)), [connections])
  const availableIntegrations = useMemo(
    () => integrations?.filter((i) => !connectedIntegrationIds.has(i.id)),
    [integrations, connectedIntegrationIds],
  )

  if (integrationsLoading || connectionsLoading) return <div>Loading...</div>

  return (
    <div>
      {/* Section 1: Connected accounts */}
      <h2>Your Connections</h2>
      {connections?.length === 0 && <p>No connections yet.</p>}
      {connections?.map((connection) => (
        <div key={connection.id}>
          <span>{connection.name}</span>
          {connection.disconnected ? (
            <button onClick={() => membrane.ui.connect({ connectionId: connection.id })}>Reconnect</button>
          ) : (
            <button onClick={() => membrane.connection(connection.id).archive()}>Disconnect</button>
          )}
        </div>
      ))}

      {/* Section 2: Available apps to connect */}
      <h2>Available Integrations</h2>
      {availableIntegrations?.map((integration) => (
        <div key={integration.key}>
          <img src={integration.logoUri} alt='' width={24} />
          <span>{integration.name}</span>
          <button onClick={() => membrane.ui.connect({ integrationKey: integration.key })}>Connect</button>
        </div>
      ))}
    </div>
  )
}
```

Once an integration is connected, it moves from "Available Integrations" to "Your Connections" automatically.

See the [Playground](https://github.com/membranehq/playground) for a full working example with styling and additional features.

### Hooks reference

| Hook                | Returns                                                                         |
| ------------------- | ------------------------------------------------------------------------------- |
| `useIntegrations()` | `{ items: Integration[], loading, error }` — all integrations in your workspace |
| `useConnections()`  | `{ items: Connection[], loading, error }` — current tenant's connections        |
| `useMembrane()`     | The `MembraneClient` instance for imperative operations                         |

Pass `{ search: query }` to `useIntegrations` to add search filtering.

## JavaScript SDK

For non-React apps, use the JavaScript SDK directly.

```bash theme={null}
npm install @membranehq/sdk
```

```javascript theme={null}
import { MembraneClient } from '@membranehq/sdk'

const membrane = new MembraneClient({
  fetchToken: async () => {
    const response = await fetch('/api/membrane-token')
    const { token } = await response.json()
    return token
  },
})

// List available integrations
const integrations = await membrane.integrations.find()

// List current tenant's connections
const connections = await membrane.connections.find()

// Connect to an app (opens popup)
await membrane.ui.connect({ integrationKey: 'hubspot' })

// Reconnect a disconnected connection
await membrane.ui.connect({ connectionId: 'con_abc123' })

// Disconnect
await membrane.connection('con_abc123').archive()
```

## REST API

For any language or framework, use the REST API directly.

**List integrations:**

```
GET https://api.getmembrane.com/integrations
Authorization: Bearer {TOKEN}
```

**List connections:**

```
GET https://api.getmembrane.com/connections
Authorization: Bearer {TOKEN}
```

**Connection UI:** Redirect your user to Membrane's hosted connection page:

```
https://ui.getmembrane.com/embed/integrations/{INTEGRATION_KEY}/connect?token={TOKEN}
```

Optional parameters: `redirectUri` (where to send the user after connecting), `name` (pre-set connection name). Every completed connect flow creates a new connection; to re-authenticate an existing connection, pass its `connectionId`.

**Reconnect:** Redirect to:

```
https://ui.getmembrane.com/embed/connections/{CONNECTION_ID}/refresh?token={TOKEN}
```

See the full [API Reference](/reference) for all available endpoints.

## Advanced

* [Embedded UI](/docs/ways-to-use-membrane/embedded-ui) — customize the connection flow and manage app re-authentication
* [Custom Connection UI](/docs/ways-to-use-membrane/embedded-ui/connection-ui/custom-connection-ui) — build a fully custom connection experience
* [Connection Lifecycle](/docs/how-membrane-works/connections) — auto-refresh, reconnection, webhooks
