> 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/set-up-connector-library.md).

# Set up the connector library (admin)

This guide is for **platform administrators**. It explains how to populate the [Ready-to-use APIs](/guides/ready-to-use-connectors.md) catalog that workspaces browse.

The catalog is empty until you point FlowCP at a git repository of connector definitions and run a sync. (Unlike the remote-connector library, it ships no built-in seed — an empty catalog on first run is expected, not a bug.)

## How it works

Connector definitions live in a git repo — one folder per connector. A platform-level **library source** records which repo/branch/directory to sync from. A background job mirrors each connector folder into a `ConnectorTemplate` row; those rows are what workspaces see under **Ready-to-use APIs**. The sync job is the only thing that reads GitHub — instantiation and re-imports read the stored spec, so they never hit rate limits.

## 1. Create the connector repo

Create a repo (for example `inovastudio/apis-library`) with one folder per connector under a root directory (default `connectors/`):

```
connectors/
  github/
    connector.yaml
    openapi.json          # or openapi.yaml / openapi.yml
  acme-crm/
    connector.yaml
    openapi.json
```

* The **folder name is the connector slug** and must match `^[a-z0-9][a-z0-9-]{1,62}$`.
* **`connector.yaml`** carries the connector's metadata and its non-secret OAuth defaults. It must **never contain a secret** — any secret-shaped key (`clientSecret`, `token`, `password`, …) causes the whole manifest to be rejected. Each workspace supplies its own credentials at instantiate time.

```yaml
formatVersion: 1
name: GitHub
description: Repos, issues, and pull requests via the GitHub REST API.
category: Developer Tools
apiBaseUrl: https://api.github.com # https only
docsUrl: https://github.com/settings/developers # where a user creates their OAuth app
authMode: user_oauth # user_oauth | api_key | bearer | none
oauth: # required when authMode: user_oauth
  provider: oauth2 # oauth2 needs explicit URLs below;
  authorizeUrl: https://github.com/login/oauth/authorize #   named providers (auth0,
  tokenUrl: https://github.com/login/oauth/access_token #   okta, …) resolve via metadata
  scopes: repo read:user
  # metadata: { }                                 # optional non-secret provider params
sortOrder: 10
# For authMode: api_key, omit `oauth` and instead give the placement:
# authConfig: { in: header, name: X-API-Key }
```

The manifest schema is enforced by `parseConnectorManifest` in `@flowcp/shared` — the single source of truth for the format. A repo CI check can import it to validate every `connector.yaml` before merge.

## 2. Install the FlowCP GitHub App on the repo

The library sync reuses the same GitHub App as git-backed app sources. Install it on the connector repo (or grant your existing org installation access to it), then note the **installation ID** — find it under GitHub → org **Settings → Applications → FlowCP → Configure** (the page URL ends in `installations/<id>`), or from your account's git connection in FlowCP.

## 3. Allowlist admin emails

The library admin endpoints are gated by an environment allowlist and fail closed when it's unset. Set it on the **API service** and redeploy:

```
ADMIN_EMAILS=you@example.com,teammate@example.com
```

## 4. Configure the source and sync

There is no admin UI or dashboard token page. The simplest way to do the one-time setup is the bundled **`setup-library`** script, run from a trusted shell that already has the API's environment — the **API service console** (e.g. on Railway). It calls the sync service directly, so it needs no token and is not subject to the `ADMIN_EMAILS` gate (that only guards the HTTP endpoints in the next section).

```bash
# 1. List the GitHub App installations this instance knows about (or print where
#    to find the id on GitHub). Run with no id first:
pnpm library:setup

# 2. Re-run with the installation id for the org that owns the connector repo.
#    Owner/repo default to inovastudio/apis-library; override with
#    LIBRARY_REPO_OWNER / LIBRARY_REPO_NAME / LIBRARY_REF / LIBRARY_ROOT_DIR.
LIBRARY_INSTALLATION_ID=<id> pnpm library:setup
```

It configures the library source (probing the repo first — this fails if the root directory is empty or unreachable, so create the repo **with** its `connectors/` folder before running), then runs one sync and prints the result, e.g. `{ scanned, upserted, failed, delisted, reimportedServers }`. Once a connector syncs, it appears on the **Ready-to-use APIs** tab immediately. A non-zero `failed` count means one folder's `connector.yaml`/spec is invalid — the per-folder error is logged with its slug.

### HTTP endpoints (alternative)

The same operations are exposed as admin HTTP endpoints, authenticated as a user whose email is in `ADMIN_EMAILS` (`ref`/`rootDir` optional, default `main` / `connectors`):

```bash
curl -X PUT https://api.flowcp.ai/admin/library/source \
  -H "Authorization: Bearer <admin token>" \
  -H "Content-Type: application/json" \
  -d '{"installationId":"<id>","repoOwner":"inovastudio","repoName":"apis-library","ref":"main","rootDir":"connectors"}'

curl -X POST  https://api.flowcp.ai/admin/library/sync      -H "Authorization: Bearer <admin token>"
curl         https://api.flowcp.ai/admin/library/templates  -H "Authorization: Bearer <admin token>"
```

An admin token is a FlowCP API token for an allowlisted user, created with the `flowcp` CLI (`flowcp token create`) — there is no dashboard page for it.

## Keeping the catalog current

* **Auto-sync on merge.** After the one-time setup, a merged pull request into the tracked branch triggers a sync automatically through the existing GitHub webhook — no manual step.
* **Fail closed per folder.** A bad manifest or spec in one connector is recorded as a `syncError` (visible in `GET /admin/library/templates`) and skipped; the rest of the catalog is unaffected, and a previously-good spec is retained.
* **Delisting.** Deleting a connector's folder marks its template `delisted` — hidden from browse and instantiate, but never deleted, so workspaces that already instantiated it keep working.

## Endpoint reference

| Method & path                  | Purpose                                         |
| ------------------------------ | ----------------------------------------------- |
| `GET /admin/library/source`    | The configured repo pointer + last sync status  |
| `PUT /admin/library/source`    | Set/replace the repo pointer (probes it first)  |
| `POST /admin/library/sync`     | Trigger a catalog sync now                      |
| `GET /admin/library/templates` | All templates, including delisted + `syncError` |

All four require an authenticated user whose email is in `ADMIN_EMAILS`.
