> For the complete documentation index, see [llms.txt](https://docs.flowcp.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flowcp.ai/guides/connect-your-api.md).

# Connect your API

This guide walks through connecting an API to FlowCP and understanding the import process. FlowCP supports any API that publishes a Swagger/OpenAPI document via the **Generic OpenAPI** provider, a **Bubble** provider with extra conveniences for Bubble apps, a **Git repository** provider that reads the document from source control and re-imports automatically on PR merge, and a **Manual** provider for APIs that have no spec at all.

## Choosing a provider

In the FlowCP dashboard, click **New connection** in the sidebar (or navigate to `/connect`) and choose a **Provider** on step 1:

* **Generic OpenAPI** — connect any API by pasting its Swagger/OpenAPI document URL directly. Start with [Connecting a generic OpenAPI API](#connecting-a-generic-openapi-api).
* **Bubble** — connect a Bubble app by its app identifier; FlowCP discovers the Swagger spec, reads app metadata, and creates Live/Main branches. Start with [Connecting a Bubble app](#connecting-a-bubble-app).
* **Git repository** — connect an OpenAPI document stored in a GitHub repository (via the FlowCP GitHub App) or any git host that exposes a raw file URL. Start with [Connecting from a Git repository](#connecting-from-a-git-repository).
* **Manual** — connect an API that has **no Swagger/OpenAPI document**. You provide just the base URL and auth, then add tools by hand. Start with [Connecting a manual API](#connecting-a-manual-api).

The first three providers end at the same place: a set of imported MCP tools you review, enable, and publish. The Manual provider skips import entirely — you author tools yourself on the Tools page (see [Add a tool manually](/guides/review-and-customize-tools.md#add-a-tool-manually)).

## Connecting a generic OpenAPI API

Choose **Generic OpenAPI** on step 1. The wizard has two steps — there is no separate ownership-verification step.

### Step 1 — App details

| Field                     | What to enter                                                                                                                                  |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| **Display name**          | A label for this app inside FlowCP (e.g. "My SaaS")                                                                                            |
| **Swagger / OpenAPI URL** | The full URL to your OpenAPI 3.x (or Swagger 2.0) document, in JSON or YAML, e.g. `https://api.example.com/openapi.json` or `.../openapi.yaml` |

Optionally set an **API base URL** if the host that serves your endpoints differs from the document's origin; otherwise FlowCP uses the document's origin.

Click **Continue to import**. FlowCP **verifies reachability** by fetching the document right then: ownership is established by FlowCP being able to reach your Swagger document, so the app is only created if the URL is reachable and returns a valid OpenAPI document (JSON or YAML). If it can't be fetched, you stay on step 1 with an error explaining what to fix — nothing is created. (This is the fail-closed behavior; FlowCP never assumes an app exists for an unreachable URL.)

### Step 2 — Import

A single **Default** MCP server is created for the document you connected, and its import runs immediately. The wizard shows progress and redirects you to the **Tools** section when it finishes.

Endpoints are classified generically from the HTTP method and path shape (`GET /users` → list, `GET /users/{id}` → get, `POST /users` → create, `DELETE /users/{id}` → delete, and so on), and tool names prefer the spec's `operationId` when present.

> **OAuth for generic apps.** When you set up OAuth for a generic app, you provide the provider's `authorize` and `token` URLs (and scopes) yourself, rather than FlowCP deriving them. See [Configure OAuth](/guides/configure-oauth.md).

## Connecting from a Git repository

Choose **Git repository** on step 1 to import an OpenAPI document that lives in source control. Like the generic provider, the wizard has two steps and no separate ownership-verification step — ownership is established by FlowCP being able to read the file. FlowCP can also **re-import automatically when a pull request is merged** into the tracked branch.

Pick a **Source**:

* **GitHub** — connect your GitHub account once (under **Account Settings**), then pick a repo from the dropdown. The dropdown lists repositories across every GitHub account/org you've connected.
* **GitLab** — connect GitLab (gitlab.com or your self-managed instance) once under **Account Settings**, then pick a project from the dropdown.
* **Other git (raw URL)** — for Bitbucket or self-hosted git: supply a raw-file URL template with an optional access token.

> GitHub and GitLab connections live at the **account level**, not per app — see [Manage Git connections](#manage-git-connections-account-settings). Connect once and every app you create reuses that connection.

> **Document format.** The **OpenAPI file path** can point at a JSON or YAML document — `.json`, `.yaml`, and `.yml` are all supported. FlowCP parses the file by content, so the extension is informational; a YAML OpenAPI spec imports exactly like its JSON equivalent. The same applies to a Generic OpenAPI URL.

### Step 1 — App details (GitHub)

1. If you haven't connected GitHub yet, click **Connect GitHub**. You'll be sent to GitHub to install (or configure) the **FlowCP** GitHub App and choose which repositories it can read. After installing, GitHub returns you to the wizard and your connection is saved to your account.
2. Choose the **Repository** from the dropdown — it's populated from your connected GitHub account(s) with no re-authorization. FlowCP pre-fills the **Branch** with the repository's default branch.
3. Set the **OpenAPI file path** — the path to the document inside the repo, e.g. `docs/openapi.json`.

| Field                 | What to enter                                                  |
| --------------------- | -------------------------------------------------------------- |
| **Display name**      | A label for this app inside FlowCP                             |
| **Repository**        | The repo the FlowCP GitHub App can read                        |
| **Branch**            | The branch to import from (and watch for merges), e.g. `main`  |
| **OpenAPI file path** | Path to the document within the repo, e.g. `docs/openapi.json` |

### Step 1 — App details (GitLab)

1. Confirm the **GitLab instance** — `https://gitlab.com` by default, or your self-managed GitLab URL.
2. If you haven't connected this GitLab instance yet, click **Connect GitLab**. You'll be sent to GitLab to authorize FlowCP (read-only). After authorizing, GitLab returns you to the wizard and the connection is saved to your account.
3. Choose the **Project** from the dropdown — populated from your connected GitLab account with no re-authorization. FlowCP pre-fills the **Branch** with the project's default branch.
4. Set the **OpenAPI file path** — the path to the document inside the project, e.g. `docs/openapi.json`.

| Field                 | What to enter                                                     |
| --------------------- | ----------------------------------------------------------------- |
| **GitLab instance**   | `https://gitlab.com` or your self-managed GitLab URL              |
| **Project**           | The project FlowCP may read                                       |
| **Branch**            | The branch to import from (and watch for merges), e.g. `main`     |
| **OpenAPI file path** | Path to the document within the project, e.g. `docs/openapi.json` |

> FlowCP stores only a (rotating) refresh token on your **account-level GitLab connection**, encrypted at rest, and never the access token — it is refreshed on demand each time the document is read. Apps reference that connection rather than holding their own token.

### Step 1 — App details (Other git / raw URL)

| Field                 | What to enter                                                                                                  |
| --------------------- | -------------------------------------------------------------------------------------------------------------- |
| **Raw URL template**  | A raw-file URL with `{ref}` and `{path}` placeholders, e.g. `https://gitlab.com/group/repo/-/raw/{ref}/{path}` |
| **Access token**      | Optional. For private repos; stored encrypted and sent as a Bearer token when fetching                         |
| **Branch**            | Substituted for `{ref}`                                                                                        |
| **OpenAPI file path** | Substituted for `{path}`                                                                                       |

Click **Continue to import**. FlowCP **verifies reachability** by fetching the document right then. If it can't be fetched, you stay on step 1 with an error and nothing is created (fail-closed).

### Step 2 — Import

A single **Default** MCP server is created and its import runs immediately, exactly as for the generic provider. Endpoints are classified generically from the HTTP method and path shape.

### Import skills, widgets, prompts, resources, and docs from the repo

For **GitHub** and **GitLab** sources, the import also discovers MCP content from five fixed top-level directories in the same repository, alongside the tools it generates from the OpenAPI document. These match the [standard FlowCP folder](/guides/folder-format.md) layout:

| Directory    | Imports as          | File format                                                                                                             |
| ------------ | ------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `Skills/`    | Skills              | `<name>.md` — `---`-fenced frontmatter (`description`, `references`, `sortOrder`) + body                                |
| `Prompts/`   | Prompts             | `<name>.md` — frontmatter (`title`, `description`, `arguments`, `resources`, `sortOrder`) + body                        |
| `Widgets/`   | Widgets             | `<name>.html` (the widget HTML) + an optional `<name>.json` sidecar (`description`, `csp`, `sortOrder`)                 |
| `Resources/` | Resources (static)  | `<name>.md` — frontmatter (`title`, `description`, `uriTemplate`, `mimeType`, `uriVariables`) + body (the content)      |
| `Docs/`      | Documentation pages | `<slug>.md` or `.mdx` — frontmatter (`title`, `description`, `sortOrder`) + body. **Nested**: the file path is the slug |

* The **file name** (without extension) becomes the item name. `Docs/` is the exception: the file's whole path below `Docs/` becomes the page slug, so `Docs/guides/webhooks.md` is served at `docs://guides/webhooks`. It is also the only directory walked recursively (up to three levels). See [Serve product documentation](/guides/serve-product-docs.md).
* Directory names may be Capitalized (`Skills/`, as above) or lowercase (`skills/`) — both import identically.
* This is the same on-disk format the [`flowcp sync`](/reference/cli.md) CLI reads and writes, so a repo you commit by hand and one you push with `flowcp sync push` import identically.
* Repo resources are always **static** (a repo file can't reference a server-specific backing tool). Add or auto-generate endpoint resources from the [Resources](/guides/review-and-customize-tools.md) page instead.
* Imported items arrive **disabled** — like tools, they are default-deny and won't reach your live MCP server until you enable them on the Skills / Widgets / Prompts / Resources / Documentation pages.
* Re-imports are idempotent: they update content but never change your enabled/sort-order choices, and never overwrite an item you created or edited by hand in the dashboard (same name → the repo file is skipped).
* **Other git (raw URL)** sources import tools only — FlowCP can't enumerate directories over a raw-file URL, so content import is skipped for them.

### Auto-import on PR merge

Once connected, FlowCP re-imports the document whenever a pull request is **merged into the tracked branch** — your enabled tools and customizations are preserved (re-import is idempotent; see [Re-importing](#re-importing)).

* **GitHub:** auto-import works as soon as the FlowCP GitHub App is installed — the App receives pull-request events and FlowCP acts only on merges into your tracked branch.
* **GitLab:** in GitLab → **Settings → Webhooks**, add a webhook pointing at the GitLab webhook URL shown on the app's settings page, enable the **Merge request events** trigger, and paste the per-app secret as the **Secret token**. For security the secret is never displayed — click **Copy** next to **Secret token** to copy it to your clipboard. FlowCP acts only on merge requests merged into your tracked branch.
* **Other git:** add a webhook in your git host pointing at the generic webhook URL shown on the app's settings page, using the per-app secret to sign requests. For security the secret is never displayed — click **Copy** next to **Webhook secret** to copy it. Any signed request triggers a fresh import.

You can also trigger a manual re-import at any time from the app's settings.

### Manage Git connections (Account Settings)

GitHub and GitLab connections belong to **your user account**, so you authorize once and reuse the connection across every app and workspace you belong to. Manage them under **Settings → Account → Git connections**:

* **Connect GitHub** installs the FlowCP GitHub App on an account or org. You can connect several — the connect wizard's repository dropdown aggregates repositories across all of them.
* **Connect GitLab** authorizes a GitLab instance (gitlab.com or self-managed). You can connect more than one instance.
* **Disconnect** removes FlowCP's stored connection. Existing apps that imported from it keep their resolved document, but auto re-import and the picker stop working for that connection until you reconnect. (Disconnecting GitHub here forgets the installation in FlowCP; to fully revoke access, also uninstall the FlowCP GitHub App from GitHub.)

For finer control from CI — for example to also run the MCP test suite and publish only when it passes — drive the `flowcp` CLI from a workflow instead of (or alongside) auto-import. See [Use FlowCP in GitHub Actions](/guides/github-actions.md).

### Editing the git source later

Everything you set when connecting is editable from **Settings → General** under the **Git source & auto-import** card:

* **Branch** and **OpenAPI file path** — change either and click **Save git source**. FlowCP re-resolves the document, validates it is reachable (saving fails if it isn't), and re-imports every branch's tools from the new location.
* **Other git (raw URL)** sources can also edit the **Raw URL template** and replace the stored **Access token** (leave the token blank to keep the current one).
* **Change repository** (GitHub) / **Change project** (GitLab) re-runs the GitHub/GitLab connect so you can point the app at a different repo or project, then returns you to the settings page to pick it and save.

The card also shows the current webhook URL (GitLab / Other git), a **Copy** button for the webhook secret (the secret itself is never displayed), and the last imported commit.

## Connecting a manual API

Choose **Manual** on step 1 when your API has **no Swagger/OpenAPI document** to import — you'll define each tool by hand instead. The wizard is a single step: there is no ownership verification and no import.

### Step 1 — App details

| Field              | What to enter                                                                                     |
| ------------------ | ------------------------------------------------------------------------------------------------- |
| **Display name**   | A label for this app inside FlowCP (e.g. "My API")                                                |
| **API base URL**   | The origin your tools call, e.g. `https://api.example.com`. Each tool's path is appended to it    |
| **Authentication** | How tools authenticate to your API: **No auth**, **API key**, **Bearer token**, or **User OAuth** |

For **API key**, also choose the **placement** (a request header or a query parameter) and its **name** (e.g. `X-API-Key`), and enter the key. For **Bearer token**, enter the token (sent as an `Authorization: Bearer …` header). Shared credentials are stored encrypted at rest and never returned. Choose **User OAuth** to run every call in the end-user's own authorization context — you configure the OAuth provider afterward under [Configure OAuth](/guides/configure-oauth.md).

Click **Connect and add tools**. FlowCP creates the app (already verified — you own the credential you provided) plus its default MCP server with the auth you chose, then takes you straight to the **Tools** page. From there, use **Add tool** to author your first tool — see [Add a tool manually](/guides/review-and-customize-tools.md#add-a-tool-manually).

Manual tools inherit the app's base URL and auth automatically; you only specify each tool's method, path, and input parameters.

## Connecting a Bubble app

Choose **Bubble** on step 1. The Bubble provider adds automatic Swagger discovery, ownership verification, and Live/Main branches.

### Prerequisites

Your Bubble app must have its API and Swagger schema enabled before FlowCP can import it. In Bubble:

1. Go to **Settings → API**
2. Enable **"Enable the Bubble API"**
3. Uncheck **"Hide Swagger Schema"** (if checked, FlowCP cannot access the endpoint list)
4. Make sure the endpoints you want to expose are set to **Public** or accessible to authenticated users

### Step 1 — App details

| Field             | What to enter                                                                             |
| ----------------- | ----------------------------------------------------------------------------------------- |
| **Display name**  | A label for this app inside FlowCP (e.g. "My SaaS")                                       |
| **Bubble App ID** | The subdomain of your Bubble app. If your app is at `myapp.bubbleapps.io`, enter `myapp`. |

Click **Continue to verification**. FlowCP reads your app's Bubble metadata (`/api/1.1/meta`) to detect a **custom Live domain** when one is configured. You can override it later under **Settings** for the app.

### Step 2 — Verify ownership

Prove you control the app by adding a verification page. If your Bubble app has run-mode protection enabled, you can also enter the optional username and password on this step so FlowCP can reach protected run-mode URLs. See [Verifying app ownership](#verifying-bubble-app-ownership) below.

### Step 3 — Import

After verification, FlowCP checks the Swagger endpoint for both default Bubble branches and imports whichever branches are reachable:

* **Live** → live Swagger URL (custom domain when detected, otherwise `https://<app-id>.bubbleapps.io/api/1.1/meta/swagger.json`)
* **Main** → the default development version: `https://<app-id>.bubbleapps.io/version-test/api/1.1/meta/swagger.json`

The wizard shows a real-time progress indicator for each imported branch independently. Once the available imports succeed, you are automatically redirected to the **Tools** section.

If neither Live nor Main has a reachable Swagger endpoint, the wizard displays instructions to enable it in Bubble (see [Troubleshooting](/support/troubleshooting.md)).

You can add more branches (e.g. a named Bubble branch served at `/version-<id>/`) or delete any branch — including the defaults — from the **Settings → Branches** page. See [Managing branches](/guides/manage-branches.md).

### Verifying Bubble app ownership

Before importing, FlowCP requires you to prove you control the Bubble app. This is a one-time step per app.

During the connect flow, step 2 (**Verify ownership**) walks you through this. You can also open **Settings → Verify** for the app (`/apps/<app-id>/settings/verify`) from the import screen (**Go to Verify**) if you need to finish or reverify later.

1. Copy the verification token shown on the page.
2. In the Bubble editor, create a new page and set its URL slug to exactly that token (the page content does not matter).
3. If your app has Bubble run-mode protection, fill the optional **Username** and **Password** fields. Bubble protected URLs follow the form `http://username:password@appid.bubbleapps.io/`; FlowCP sends the equivalent basic-auth header and stores the password encrypted for future verification and Swagger imports.
4. Publish the page in Bubble, then click **Check Verification** in FlowCP.

FlowCP probes both your live and version-test versions. Once found, the page shows a green **App Verified** card confirming ownership.

#### Reverifying

If you transfer the app to a different Bubble account or change its base URL, you can reverify at any time:

1. Open **Settings → Verify** (`/apps/<app-id>/settings/verify`), for example via **Go to Verify** on the import page.
2. Click **Reverify** — a new token is generated.
3. Create a new Bubble page with the updated token and publish it.
4. Update the optional run-mode username/password if they changed.
5. Click **Check Verification** again.

### Custom domains (Bubble)

If your Bubble app uses a custom domain for Live (e.g. `inova.us`), FlowCP detects it from Bubble's `/api/1.1/meta` response when you connect. Live OAuth, imports, and MCP tool calls then use that host instead of `*.bubbleapps.io`.

If detection fails (API disabled or meta unreachable), set the domain manually under the app's **Settings** page.

## Managing branches

After the import step completes, you are redirected to the **Tools** section where you can enable and configure the imported tools. You can also open **Settings → Branches** to review each branch server, trigger a fresh import, create a new branch, or delete one. See [Managing branches](/guides/manage-branches.md).

## Understanding the import status

FlowCP runs each branch's import asynchronously — the import status page polls for updates.

| Status         | Meaning                                                                            |
| -------------- | ---------------------------------------------------------------------------------- |
| **Pending**    | The import job is queued.                                                          |
| **Processing** | FlowCP is fetching and parsing the Swagger spec.                                   |
| **Complete**   | All endpoints have been imported and tools created.                                |
| **Failed**     | The import could not complete. See [Troubleshooting](/support/troubleshooting.md). |

While an import or re-import runs, the page shows a live **checklist** that steps through each kind of thing FlowCP imports, settling each row with the number it imported:

* **Tools** and **Resources** — imported for every app.
* **Skills**, **Prompts**, **Widgets**, and **Documentation** — imported only for Git (GitHub/GitLab) apps from your repo's `Skills/`, `Prompts/`, `Widgets/`, and `Docs/` directories. These rows are hidden for Bubble and Generic OpenAPI apps.

If the import fails, the checklist highlights the step that failed and the error summary is shown below it.

Once the import completes, the page lists all discovered endpoints. Proceed to the [Tools tab](/guides/review-and-customize-tools.md) to enable the ones you want.

## App details

Open the app's **Settings** page (`/apps/<app-id>/settings`) to edit how the app appears across the dashboard:

* **App name** — the display name for the app. Pre-filled from what you entered when connecting; edit it any time.
* **Description** — an optional short summary of what the app does and what its MCP server exposes. Leave blank to clear it.
* **Logo URL** — an optional public image URL used as the app's logo. A small preview appears next to the field; leave blank to remove the logo.
* **Website** — an optional public homepage URL. It is surfaced to MCP clients alongside the logo and description so users can find your product. Leave blank to omit it.

The description, logo, and website are advertised to MCP clients when they connect (see [How the server appears in your AI client](/guides/publish-your-mcp-server.md#how-the-server-appears-in-your-ai-client)).

Edit any of these fields and click **Save app details**. Changes here only affect the app's presentation — they do not touch your Swagger URLs, branches, or imported tools.

### Updating the Swagger URL (OpenAPI apps)

For apps connected from a generic OpenAPI document, the **Settings** page also has a **Swagger URL** card. Paste a new OpenAPI 3.x or Swagger 2.0 document URL into the **Swagger / OpenAPI URL** field and click **Save Swagger URL** to point the app at a different spec — for example, if the document has moved or you need to correct the URL. FlowCP checks the new URL is reachable before saving, then re-imports the app's tools from it.

Bubble apps don't have this field: their Swagger URL is derived automatically from the app's base URL and [custom domain](#custom-domains-bubble), so there's nothing to edit directly.

### Changing an app's provider

If you connected an app under the wrong provider — or you want to migrate it (for example, move an OpenAPI spec into a Git repository) — click the **Change provider** button on the **Settings** page to open the change-provider popup instead of deleting and re-creating the app. Pick the new provider (Bubble, Generic OpenAPI, or Git repository) and fill in its details, exactly as on the connect screen. For GitHub and GitLab you connect the repository or project through the same OAuth round-trip, which returns you to the settings page.

Changing the provider is **destructive** and only available to workspace owners:

* It deletes all of the app's current branches, tools, and execution logs, then re-imports tools from the new source under that provider's adapter.
* It **resets the app's OAuth configuration.** OAuth credentials and authorize/token URLs are specific to the old provider and API, so they can't authenticate the new one — they are removed and the re-provisioned branches start with **no OAuth config assigned**.
* Switching **to** Bubble resets the app to **unverified** — you must [re-verify ownership](#verifying-bubble-app-ownership) before its tools can be imported again. Switching to Generic OpenAPI or Git verifies the app immediately by reaching the document.
* The popup summarizes these effects alongside the form before anything changes. FlowCP checks the new source is reachable first (fail closed), so a bad URL leaves the app untouched.
* If any branch is **published**, unpublish it first — re-provisioning would break MCP clients connected to that server.

After switching, **set up OAuth again** from scratch on the [OAuth configuration](/guides/configure-oauth.md) page and assign a config to each branch — until you do, those branches fail closed and can't authorize end users.

## Re-importing

You can trigger a fresh import at any time from the app's settings. Re-importing is safe — it updates existing tool records and adds any new endpoints found in the Swagger spec. Tools you have already customized (renamed, description edited) are not overwritten unless the underlying endpoint definition changed.

Every import is recorded in the server's **spec import history** — open **Servers → History** and switch to the **Spec imports** tab to see each import, whether it changed anything, and a per-endpoint diff of what changed in the upstream API since the previous import (including a warning when enabled tools reference endpoints the API removed). See [Version History — Spec import history](/guides/version-history.md#spec-import-history).

The full raw spec document is retained for the three most recent valid imports per server; older imports keep the normalized endpoint list used for diffs.
