configuring-connections — скилл для Claude Code: обзор и установка
Помогает настроить подключения Celigo и объекты iClients для интеграций с внешними API, базами данных и облачными сервисами.
npx skills add celigo/ai --skill configuring-connections -a claude-codeЧто делает configuring-connections
Скилл даёт агенту инструкции по созданию и редактированию подключений (connections) и общих хранилищ учётных данных (iClients) в платформе Celigo. Каждое подключение связывает интегратор с внешней системой: REST- или GraphQL-сервисами, базами данных или NetSuite. Без него настроить интеграцию нельзя. Агент помогает выбрать метод авторизации — от токенов и basic auth до OAuth2 и ролей AWS IAM.
Работа с аккаунтом ведётся через инструменты Celigo вроде list_connections и upsert_connection или через утилиту celigo CLI. Секреты требуют точности. При полном обновлении конфигурации важно возвращать все маскированные строки ровно в том виде, как они прочитаны, иначе сохранённые ключи затрутся. Отдельное правило действует для GraphQL. Изменение http.relativeURI вручную не сработает, потому что встроенный редактор сбрасывает путь обратно на / при каждом сохранении.
Какие задачи решает
- выбрать метод авторизации для внешнего API в Celigo
- создать общее хранилище учётных данных iClient для OAuth или облачной роли
- настроить лимиты параллельных запросов concurrencyLevel между подключениями
- диагностировать ошибки подключения и переход статуса в offline
Примеры запросов агенту
- Помоги настроить подключение к NetSuite через token-auto в Celigo
- Создай iClient для OAuth-авторизации приложения Salesforce
- Проверь, почему соединение с базой данных перешло в статус offline
Как установить configuring-connections
1Через Skills CLI (Vercel)
npx skills add celigo/ai --skill configuring-connections -a claude-code2Вручную: положить файлы
~/.claude/skills/configuring-connections/SKILL.mdПапка скилла целиком; для одного проекта — .claude/skills/configuring-connections/
1Через Skills CLI (Vercel)
npx skills add celigo/ai --skill configuring-connections -a codex2Вручную: положить файлы
.agents/skills/configuring-connections/SKILL.mdДля всех проектов — ~/.agents/skills/
1Через Skills CLI (Vercel)
npx skills add celigo/ai --skill configuring-connections -a cursor2Вручную: положить файлы
.cursor/skills/configuring-connections/SKILL.mdCursor читает и .agents/skills/, и .claude/skills/
1GitHub CLI
gh skill install celigo/ai configuring-connections2Вручную: положить файлы
.github/skills/configuring-connections/SKILL.md1Через Skills CLI (Vercel)
npx skills add celigo/ai --skill configuring-connections -a gemini-cli2Командой платформы
gemini skills install https://github.com/celigo/ai --path skills/configuring-connectionsВручную: положить файлы
.devin/skills/configuring-connections/SKILL.mdСтарый путь .windsurf/skills/ тоже читается
Через Skills CLI (Vercel)
npx skills add celigo/ai --skill configuring-connections -a opencodeClaude.ai
Упакуйте папку в zip и загрузите в Settings → Capabilities → Skills
По шагам, с командами для каждой платформы: Как установить скилл в Claude Code: пять способов
Вопросы о configuring-connections
Как установить configuring-connections в Claude Code?
Выполните команду npx skills add celigo/ai --skill configuring-connections -a claude-code. Скилл запишется в файл ~/.claude/skills/configuring-connections/SKILL.md.
Что делает configuring-connections?
Скилл передаёт агенту схемы и правила для настройки соединений Celigo с внешними платформами. В него входят параметры аутентификации, пулы параллельных вызовов и управление хранилищами iClients.
Как правильно обновлять учётные данные подключения?
При полном обновлении документа нужно отправлять обратно все маскированные секреты точно так, как они были прочитаны. Другой вариант — точечно менять отдельное поле из белого списка, чтобы не стереть сохранённые токены.
Исходный текст
SKILL.md · MIT
---
name: configuring-connections
description: Configure Celigo connections and iClients -- credential and configuration objects that authenticate to external systems. Use when creating or editing connections, choosing auth methods, setting up OAuth, managing iClients (shared credential stores), or troubleshooting connectivity.
---
<!-- TIER:1 -->
# Configuring Connections
A connection is a **credential and configuration object** that lets Celigo communicate with an external system. Every export and import references a connection via `_connectionId`. Connections must be created before the resources that use them.
Concerns when configuring a connection:
- **Authentication** -- choosing the right auth method (OAuth, token, basic, key-pair, certificate, etc.) and providing the correct credentials
- **Concurrency** -- how many parallel requests Celigo can make to the target system (`concurrencyLevel`). Can be shared across connections via `_borrowConcurrencyFromConnectionId`
- **Health monitoring** -- ping configuration to verify connectivity and detect credential expiration (`offline` status)
- **Pre-built connectors** -- HTTP connectors and trading partner connectors provide pre-configured auth, base URLs, and endpoint definitions for 550+ applications
- **Debug logging** -- temporary debug mode to capture raw request/response data for troubleshooting
- **iClients** -- reusable credential stores shared across connections: an OAuth app registration (client ID/secret, scopes, token endpoints) or a cloud identity (AWS IAM role, Azure service principal, Google service account). See [iClients section](#iclients-shared-credential-stores) below.
Used across flows, APIs, and tools.
## How to Run the Steps
This skill names each step by what it reads or changes; the exact calls depend on how you reach the account. Read the one reference that matches your tools -- both follow the section and step names of this skill:
- **Celigo MCP tools** (`list_connections`, `upsert_connection`, `get_schema`, ...) -- [references/mcp.md](references/mcp.md)
- **The `celigo` CLI** -- [references/cli.md](references/cli.md)
Looking up connections, connectors, templates, and iClients only reads. Creating, updating, deleting, authorizing, registering a connection on an integration, and arming a debug window all write to the account -- do them when the user asked for the change. Diagnosing a connection only reads: when the user asks what's wrong or what to do about it, name the change and leave it to them. A single whitelisted field is a targeted change; anything else is a full-document update that sends every masked credential back exactly as read, which keeps the stored secrets, and never leaves one out -- see [Connection Operations](#connection-operations). An iClient's update works the same way -- see [iClient Operations](references/iclients.md#iclient-operations).
## Connection Types
| Target System | `type` | Schema | Notes |
|---|---|---|---|
| REST/GraphQL API (with connector) | `http` | [http.yml](references/schemas/http.yml) | `formType: "assistant"`, set `_httpConnectorId` |
| REST/GraphQL API (manual) | `http` | [http.yml](references/schemas/http.yml) | Three form types: `assistant`, `http`, `graph_ql` |
| NetSuite ERP | `netsuite` | [netsuite.yml](references/schemas/netsuite.yml) | Use `token-auto` for new connections |
| Salesforce CRM | `salesforce` | [salesforce.yml](references/schemas/salesforce.yml) | Omit `salesforce._iClientId` to use Celigo's Connected App |
| SQL Server, MySQL, Postgres, Oracle | `rdbms` | [rdbms.yml](references/schemas/rdbms.yml) | |
| Snowflake, BigQuery, Redshift | `rdbms` | [rdbms.yml](references/schemas/rdbms.yml) | Check sub-type in schema |
| Active Directory, Databricks, DB2 | `jdbc` | [jdbc.yml](references/schemas/jdbc.yml) | |
| MongoDB/Atlas | `mongodb` | [mongodb.yml](references/schemas/mongodb.yml) | |
| DynamoDB | `dynamodb` | [dynamodb.yml](references/schemas/dynamodb.yml) | |
| FTP/SFTP/FTPS server | `ftp` | [ftp.yml](references/schemas/ftp.yml) | Optional PGP encryption |
| Amazon S3 | `s3` | [s3.yml](references/schemas/s3.yml) | |
| Local filesystem | `filesystem` | [filesystem.yml](references/schemas/filesystem.yml) | Requires agent via `_agentId` |
| AS2 EDI partner | `as2` | [as2.yml](references/schemas/as2.yml) | |
| Celigo VAN (EDI hub) | `van` | [van.yml](references/schemas/van.yml) | |
| AI tool server (MCP) | `mcp` | [mcp.yml](references/schemas/mcp.yml) | |
| Stack-deployed connector | `wrapper` | [wrapper.yml](references/schemas/wrapper.yml) | |
| Legacy REST (do not use) | `rest` | [rest.yml](references/schemas/rest.yml) | Use `http` instead |
**GraphQL steps get their editor from the connection.** For a generic GraphQL API, create a `graph_ql` connection whose base URI is the GraphQL endpoint (the connection form can't switch an existing connection to it). For a connector with a GraphQL API, bind the connection to that API with `http._httpConnectorApiId` -- every step on the connection inherits it. GraphQL steps on a connection bound to the app's REST API post to the API root and every record fails (HTTP 406 on Shopify): add a second connection bound to the GraphQL API and re-point those steps to it, rather than replacing the connection on the whole flow. Patching a step's `http.relativeURI` to the GraphQL endpoint isn't a fix: the GraphQL editor writes `/` back on every save, and the step fails again.
## Quick Reference
### Connection Type Decision Matrix
| Target system | Use type | Auth method | Read schema |
|---|---|---|---|
| Any REST/GraphQL API with a Celigo connector | `http` | Connector-defined (usually OAuth2 or token) | [http.yml](references/schemas/http.yml) |
| Any REST/GraphQL API without a connector | `http` | `token`, `basic`, `oauth` (the app on an iClient), `custom` (headers or encrypted fields); also `oauth1`, `jwtbearer`, `cookie`, `digest`, `wsse`, and `awsiam` (an `awsIam` iClient) | [http.yml](references/schemas/http.yml) |
| NetSuite ERP | `netsuite` | `token-auto` (Celigo-managed TBA; only the account id) | [netsuite.yml](references/schemas/netsuite.yml) |
| Salesforce CRM | `salesforce` | OAuth through Celigo's Connected App, or the customer's via an iClient (`salesforce._iClientId`) | [salesforce.yml](references/schemas/salesforce.yml) |
| SQL databases (Postgres, MySQL, SQL Server, Oracle) | `rdbms` | Username/password + host/port | [rdbms.yml](references/schemas/rdbms.yml) |
| Snowflake / BigQuery / Redshift | `rdbms` | Snowflake: key pair or password · BigQuery: service-account key · Redshift: access-key pair or an AWS IAM role (no host or password) | [rdbms.yml](references/schemas/rdbms.yml) |
| MongoDB / Atlas | `mongodb` | Host list (`host:port`), username, password | [mongodb.yml](references/schemas/mongodb.yml) |
| FTP / SFTP / FTPS | `ftp` | Username/password or SSH key | [ftp.yml](references/schemas/ftp.yml) |
| Amazon S3 | `s3` | IAM access key pair, or an IAM role through an `awsIam` iClient | [s3.yml](references/schemas/s3.yml) |
| MCP server | `mcp` | `token`, `oauth` (an iClient), or `custom` | [mcp.yml](references/schemas/mcp.yml) |
Which of the two HTTP rows applies is determined by search, not preference: check for a pre-built connector first (search the HTTP connector catalog) and use the manual row only when no connector exists or it doesn't fit -- see [Check for a pre-built connector and global iClient](#4-check-for-a-pre-built-connector-and-global-iclient).
### Minimum Required Fields
Every connection needs at minimum: `name`, `type`, and the type-specific config block. Some of the fields below are required by the connection form rather than the API (each schema says which); send them anyway, or the connection won't connect.
| Type | Required fields |
|---|---|
| `http` (connector) | `name`, `type: "http"`, `http.formType: "assistant"` (`assistant_graphql` when the API is GraphQL), `http._httpConnectorId`, `http._httpConnectorVersionId`, `http._httpConnectorApiId` for a connector with more than one API, `http.baseURI`, `http.mediaType`, and the fields the connector's form asks for -- credentials, and settings such as `settings.storeName` |
| `http` (manual) | `name`, `type: "http"`, `http.baseURI`, `http.mediaType`, `http.auth.type` and its credentials |
| `netsuite` | `name`, `type: "netsuite"`, `netsuite.authType: "token-auto"`, `netsuite.account` (a non-production account's id carries its suffix, such as `123456_SB1`) |
| `salesforce` | `name`, `type: "salesforce"`, `salesforce.oauth2FlowType` (plus `salesforce.username` for `jwtBearerToken`), `salesforce.sandbox` |
| `rdbms` | `name`, `type: "rdbms"`, `rdbms.type`, then that database's fields in [rdbms.yml](references/schemas/rdbms.yml) -- BigQuery and Redshift take no host or password |
| `ftp` | `name`, `type: "ftp"`, `ftp.type` (`ftp`, `sftp`, `ftps`), `ftp.hostURI`, `ftp.username`, and `ftp.password` or (SFTP) `ftp.authKey` -- an unencrypted RSA key in PEM format (OpenSSH-format, passphrase-protected, and PuTTY keys aren't supported); leave `password` out for key-only SFTP |
| `s3` | `name`, `type: "s3"`, `s3.accessKeyId` and `s3.secretAccessKey`, or `s3.authType: "awsIam"` and `s3._iClientId` |
| `mongodb` | `name`, `type: "mongodb"`, `mongodb.host` (an array of `host:port`), `mongodb.username`, `mongodb.password` |
**NetSuite.** `token-auto` needs only the account: Celigo supplies the OAuth client, so a `token-auto` connection needs no iClient. REST steps (SuiteTalk records, SuiteQL, custom RESTlets) run on the same `netsuite` connection -- don't build an `http` connection for them (a REST step on one is refused with 422 `invalid_connection_type`). SuiteTalk and SuiteQL need NetSuite's REST Web Services feature; a NetSuite 403 `FEATURE_DISABLED` means it's off. `netsuite.suiteAppInstalled` reflects only the Celigo SuiteApp as detected at the last authentication and ignores the legacy bundle -- check the SuiteApp and the bundle live before calling either missing.
**A NetSuite token that stops working.** `INVALID_LOGIN_ATTEMPT` ("Invalid login attempt.") on every step and on the test of a token-based connection means NetSuite refused its token: the token was revoked or made inactive (TBA tokens don't expire), the role it's for was taken off its user, made inactive, or lost its token permission (*Log in using Access Tokens*), the integration record it was issued for was set to Blocked, or the token belongs to another account (production tokens aren't copied to a sandbox, and a refreshed sandbox needs new ones). Read the connection first and give its account, role and token by name in the answer (`netsuite.account` and `environment`, `roleName` and `roleId`, `tokenName`): they are what the NetSuite administrator checks. NetSuite's Login Audit Trail (the Detail column) says which cause it is -- [Diagnosing NetSuite Steps](../configuring-exports/references/netsuite.md#checking-a-refused-token) has where each one is checked. Nothing in Celigo fixes it: a NetSuite administrator restores the role, or creates a new access token for the user and role the connection names (`netsuite.roleName`, `roleId`); a person enters the new token on the connection in the Celigo UI (a `token-auto` connection authorizes again there, signing in with that role); then test the connection and retry the failed records. If someone offers to paste the token into chat, decline -- it goes only into the Celigo UI ([Credential Discipline](#never-accept-or-echo-real-credentials-in-chat)).
**Salesforce.** A connection authorizes through Celigo's Connected App unless `salesforce._iClientId` names an iClient holding the customer's own; don't send `packagedOAuth`, which the platform sets. Choose `oauth2FlowType`: `refreshToken` (browser authorization, the default) or `jwtBearerToken` (server-to-server; needs `username` and a Connected App with a digital certificate; a custom app's private key goes on its iClient). `sandbox` must match the org. Never write `salesforce.scope`: an empty list is normal, a save from the connection editor resets it, and a custom app's scopes live on its iClient.
**Celigo's own API** (lookup caches, jobs, Celigo Storage) is reached from a flow through a connection built from one of Celigo's two connectors. *Celigo APIs* (`assistant: "integratorceligoapi"`) authorizes with client credentials through Celigo's own iClient and needs `accessScope` on create -- `full`, `custom` (listed APIs, listeners, and Celigo Storage folder paths), or `integration` (listed integrations); a create without it is refused with 422 "Scope is required for this connection". The connection document never carries the scope -- read it from `GET /v1/accessScope/connections/{_id}`; storage paths are covered in [managing-file-storage](../managing-file-storage/SKILL.md#8-use-stored-files-in-a-flow). *Celigo integrator.io* (`integratorio`) takes an API token, which the user enters in the Celigo UI, and `settings.region` -- `.` for North America, `.eu.`, `.au.`, or `.ca.` -- which completes its base URI `https://api{{{connection.settings.region}}}integrator.io`.
### Which Schemas to Read
**Rule:** Always read the base [request.yml](references/schemas/request.yml) for shared fields, then the type-specific schema for the connection type you are configuring.
### Schema Index
**Connection schemas** (in [references/schemas/](references/schemas/)):
- **Base fields (all connections):** [request.yml](references/schemas/request.yml)
- **Response shape:** [response.yml](references/schemas/response.yml)
- **HTTP:** [http.yml](references/schemas/http.yml)
- **NetSuite:** [netsuite.yml](references/schemas/netsuite.yml)
- **Salesforce:** [salesforce.yml](references/schemas/salesforce.yml)
- **RDBMS:** [rdbms.yml](references/schemas/rdbms.yml)
- **JDBC:** [jdbc.yml](references/schemas/jdbc.yml)
- **MongoDB:** [mongodb.yml](references/schemas/mongodb.yml)
- **DynamoDB:** [dynamodb.yml](references/schemas/dynamodb.yml)
- **FTP:** [ftp.yml](references/schemas/ftp.yml)
- **S3:** [s3.yml](references/schemas/s3.yml)
- **Filesystem:** [filesystem.yml](references/schemas/filesystem.yml)
- **AS2:** [as2.yml](references/schemas/as2.yml)
- **VAN:** [van.yml](references/schemas/van.yml)
- **MCP:** [mcp.yml](references/schemas/mcp.yml)
- **Wrapper:** [wrapper.yml](references/schemas/wrapper.yml)
- **REST (legacy):** [rest.yml](references/schemas/rest.yml)
- **OAuth:** [oauth.yml](references/schemas/oauth.yml)
- **JWT:** [jwt.yml](references/schemas/jwt.yml)
- **SSL:** [ssl.yml](references/schemas/ssl.yml)
**iClient schemas** (in [references/iclient-schemas/](references/iclient-schemas/)):
- **Base fields:** [request.yml](references/iclient-schemas/request.yml)
- **Response shape:** [response.yml](references/iclient-schemas/response.yml)
- **OAuth2 providers:** [oauth2.yml](references/iclient-schemas/oauth2.yml)
- **NetSuite:** [netsuite.yml](references/iclient-schemas/netsuite.yml)
- **Salesforce:** [salesforce.yml](references/iclient-schemas/salesforce.yml)
- **eBay:** [ebay.yml](references/iclient-schemas/ebay.yml)
## Related Skills
- **configuring-exports** ([Quick Reference](../configuring-exports/SKILL.md#quick-reference)) -- choosing the right export adaptor type and schema for a data source
- **configuring-imports** ([Quick Reference](../configuring-imports/SKILL.md#quick-reference)) -- choosing the right import adaptor type and schema for a data destination
- **building-flows** ([How to Build a Flow](../building-flows/SKILL.md#how-to-build-a-flow)) -- wiring connections, exports, and imports into a flow pipeline
<!-- TIER:2 -->
## How to Build a Connection
### 1. Identify the target system
What system do you need to connect to? This determines the connection type, auth method, and configuration shape.
### 2. Name the connection after the system, not the operation
Connection names should describe the **system and environment** -- not what a specific flow does with them. Connections are shared across exports, imports, and flows, so operation-specific names become misleading as soon as a second resource uses the same connection.
| Bad (operation-specific) | Good (system/environment) |
|---|---|
| `Shopify - Customer Upsert` | `Shopify - my-store` |
| `Microsoft Dynamics 365 Business Central - Companies Export` | `Microsoft Dynamics 365 Business Central - sandbox` |
| `Stripe - Invoice Fetch` | `Stripe - Production` |
If the account has multiple environments or instances of the same system, include the distinguishing detail (store name, environment, account ID). Otherwise just the system name is fine.
### 3. Check for existing connections
Before creating a new connection, check what already exists in the account and marketplace:
- **Existing connections** -- search the account by application keyword, and list the connections with their connector identity -- match on that, not on the name (below).
- **What uses a connection** -- the exports and imports that reference it.
- **Connection health** -- offline connections that enabled flows still use, and orphaned connections that nothing uses.
- **Marketplace templates** -- search the marketplace for pre-built integration templates, and preview a template's connection model (the connections an install would need).
Reusing an existing connection avoids duplicate credentials and shares concurrency.
**Match on identity, not on the name.** Names are free text: a connection named "Shopify" may point somewhere else, and a working one may be called "Prod store". For a pre-built HTTP connector the identity is `http._httpConnectorId`, plus `http._httpConnectorApiId` when the connector has several API groups (two connections of one connector can target different APIs). `assistant` is the legacy application id -- the connector's `legacyId` -- so a connection that carries only `assistant` belongs to the connector whose `legacyId` or `legacyIds` (in the connector list) holds it, and a legacy `rest` connection is the same family as `http`. For other types it's the `type` plus its target (the NetSuite account, the database host). Two connections of the same connector and API usually point at different tenants or environments -- read the base URI or account fields before picking one. When more than one fits, prefer the one the flow or Tool you're changing already uses; otherwise confirm with the user.
**When presenting connection choices to the user**, filter out connections that are `offline: true`. Only show online/active connections as options. If ALL matching connections are offline, mention that and let the user decide whether to proceed with an offline connection or fix connectivity first.
### 4. Check for a pre-built connector and global iClient
For HTTP connections, search for a pre-built connector before configuring manually. Configure by hand only when no connector exists for the application or the connector doesn't support the auth scheme or endpoints you need:
- **HTTP connectors** (550+ apps: Shopify, Stripe, HubSpot, etc.) -- find the connector for the application name or base URL, then read the matching connector in full to see its auth config, endpoints, and resources. Where your surface offers it, scaffold the connection from the connector's own form and preview the body before anything is created.
- **Trading partner connectors** (EDI, AS2, VAN) -- search the trading partner catalog. For a partner that has one -- every published connector is AS2 or FTP -- link the connection to it (`as2._tpConnectorId` or `ftp._tpConnectorId`; published connectors only) and take the partner's host and AS2 identifiers from the user -- the connector's connection form holds only template stand-ins ([building-b2b](../building-b2b/SKILL.md#3-create-the-connection)). `as2.as2Id` (unique across all integrator.io accounts; generated when omitted) and `as2.partnerId` are fixed at creation -- a later update ignores a new value -- so never invent them. A VAN connection's `as2Id` is unique and fixed the same way (omit it to have the network assign one), and the network assigns `mailboxId`.
If an HTTP connector exists, set `http._httpConnectorId` and `http._httpConnectorVersionId` on the connection, plus `http._httpConnectorApiId` when it has more than one API. The connector provides auth templates, base URL, and pre-built endpoints. The platform resolves the link on save: an id that doesn't resolve is dropped rather than refused, and a top-level `assistant` replaces the connector id you sent -- send `assistant` only as the connector's own `legacyId`, and never on an Azure Data Lake Storage Gen2 connection, where it drops the connector ids. Read the connection back to confirm the link. A setting the connector's base URI splices into the host takes the bare identifier: Shopify's base URI is `https://{{{connection.settings.storeName}}}.myshopify.com/...`, so `settings.storeName` is `my-store`, not `my-store.myshopify.com` -- a full hostname doubles the domain, and every request goes to a host that doesn't exist.
**Check for a global iClient.** Many pre-built connectors ship with a **global (Celigo-managed) iClient** -- a shared OAuth app registration that handles authorization out of the box (e.g., Microsoft Business Central, Shopify, Google). When a global iClient is available:
- Use it by default: `http.auth.type: "oauth"` with the OAuth fields the connector's connection form pre-configures, including `http._iClientId` where the form names the global iClient.
- Do **not** fall back to static bearer token auth (`auth.type: "token"`) just because you don't have live credentials yet. Create the connection with the correct OAuth auth shape; it stays offline until the user authorizes it.
- Only create a custom iClient if the customer has their own app registration (e.g., their own Azure AD app, Shopify private app) or if the global iClient doesn't have the required scopes/consent for their tenant. Point the connection at it with `http.auth.oauth.useIClientFields: true` and `http._iClientId`. The app can't live on the connection itself: an HTTP connection doesn't store an OAuth client id or secret sent on it (the save answers 201 without them), and its authorization then fails with `unknown http authURI`.
Find the global iClient in the connector's connection form (its full definition), not on another connection. A connector OAuth connection either leaves `http._iClientId` empty -- the global iClient is applied when the user authorizes -- or names Celigo's published iClient. That iClient lives in Celigo's account, so reading it from the customer's account returns 404 `invalid_ref`, and nothing on it can be changed. That's normal, not a deleted iClient; an Integration App's connections can point at their publisher's iClient the same way.
### 5. Choose the type, auth method, and build
Use the [Connection Types](#connection-types) table above to pick the `type` value and open the matching schema for available auth options and required fields.
Every connection needs at minimum: `name`, `type`, and the type-specific config block (`http{}`, `netsuite{}`, `ftp{}`, etc.).
**Placeholder connections must use the correct auth shape.** When creating a connection without live credentials (e.g., demo, placeholder, or pre-staging), always configure the full auth structure the connection will ultimately use -- OAuth type, iClient reference, grant type, etc. This ensures the connection can be authorized in place later without reconfiguration. Never substitute static token auth as a shortcut for an OAuth connection. Don't send `offline` either: it's read-only, and only the platform's connection test sets it. A save runs that test when the connection has one -- for HTTP, only when a ping is configured -- and the result arrives in the save's response or, when the target is slow to answer, seconds later as a `system` change in the audit log. A placeholder that has a test reads offline until the user enters the credentials or authorizes it; one without a test carries no `offline` flag at all.
**An OAuth connection on an existing iClient** takes the auth shape and the reference; the iClient supplies the client, the endpoints, and the grant type:
```json
{
"name": "Acme ERP - Production",
"type": "http",
"http": {
"formType": "http",
"baseURI": "https://erp.example.com/api/v3",
"mediaType": "json",
"_iClientId": "<iClientId>",
"auth": { "type": "oauth", "oauth": { "useIClientFields": true } }
}
}
```
`_iClientId` sits on the `http` block, beside `auth`, not inside it. An authorization-code connection holds no tokens until a person authorizes it in a browser -- in the Celigo UI, or through your surface's authorize step (step 6) -- so finish by telling the user to do that.
### 6. Test the connection
Ping the connection to confirm it reaches the target system with its credentials. A ping answers HTTP 200 whether the test passed or failed, so read the body: `{code: 200}` is a pass and `{errors: [...]}` a failure -- `invalid_host` (DNS), `missing_token` (re-authorize), or a `401` with `source: application` (the remote system refused the credential). Each adaptor runs its own check: HTTP calls its configured ping endpoint -- with none configured, the test passes without sending any request -- databases open a driver session, MCP lists the server's tools (`mcp_tools_list_failed` when that list doesn't come back), NetSuite and Salesforce validate the token. A pass proves only what that check exercised; with no ping configured, or a ping endpoint that needs no auth, the first real request is the real test, so give an HTTP connection a ping on an endpoint that needs its credentials. An OAuth connection requests a token only after the target answers 401, so a ping that needs no auth passes without ever fetching one.
Authorization-code OAuth connections (and Salesforce's `refreshToken` flow) need a browser authorization first -- the tokens come from the provider's redirect, so a person completes it. The provider's app must list the redirect URI the authorization URL carries (`redirect_uri`; `https://integrator.io/connection/oauth2callback` on a North America account). The callback sets `needsAuthorization: false`; a connection never authorized has no such key, so its absence proves nothing. Each new authorization URL replaces the one before it: with PKCE (an iClient's `oauth2.pkceCodeChallengeMethod`, and every Salesforce connection) only the most recent URL can finish, so authorize once, in one window. An MCP connection authorizes the same way, through an iClient: Celigo doesn't discover a server's OAuth endpoints or register a client dynamically, so register an app with the vendor that lists the callback above, put its client and URLs on a `custom_oauth2` iClient, and expect the authorization to end with a tool listing that fails it when the server refuses the call. Client-credentials and password grants, Salesforce JWT bearer, and cloud-identity iClients need no browser step: the platform requests the token itself, and as with any connection, a test whose ping needs no auth doesn't prove those credentials. Not every surface can ping or authorize; your reference names the fallback.
## Connection Operations
Beyond building one, the operations on a connection are:
- **CRUD** -- list, read, create, update (a full-document replace), and delete
- **Test connectivity** -- ping
- **OAuth authorization** -- the browser flow that obtains the tokens
- **Debug** -- arm and disarm a debug window, and read the debug logs it captured
- **Integration-level connection management** -- register connections on an integration, or deregister them
- **Replace a connection** -- repoint steps to another connection in one call: every step of a flow, API, or Tool, or one export or import
**Targeted changes vs full updates.** Only PATCH-whitelisted fields can be changed on their own: `name`, the debug window (`debugDate`, `debugUntil`), the credential-free concurrency settings (`<adaptor>.concurrencyLevel`, `<adaptor>.targetConcurrencyLevel`, `_borrowConcurrencyFromConnectionId`, `autoRecoverRateLimitErrors` -- `<adaptor>` is the connection's `type` block, such as `http`; a path under another block is accepted and never read), and `endUserProvidedFields`. A PATCH never reads or re-sends the masked credentials GET returns as `"******"`, so it's safe. Every other field takes a full-document update: send each secret back as the masked `"******"` the GET returned, which keeps the stored secret, or as a new value. An omitted secret or a placeholder clears the stored credential -- see [Credential Discipline](#never-accept-or-echo-real-credentials-in-chat). So a PATCH refused for a header, the base URI or an auth setting means "send the full update", not "edit it in the UI": a change that keeps the stored secrets needs nothing from the user. iClients follow the same mask rule, with two provider exceptions -- see [iClient Operations](references/iclients.md#iclient-operations).
**`endUserProvidedFields`** belongs only on a connection an MCP server collects end-user credentials for: list the credential and tenant fields each end user supplies on their own copy (`http.encrypted.apiKey`, `rdbms.user`). A path the account owns -- `type`, `_agentId`, `wrapper._stackId`, any `<adaptor>._iClientId` -- is refused with 422 `mcp_end_user_provided_field_not_allowed`. A full update that leaves the field out keeps it (send `null` to clear it), and any change to the list makes every end user set up again.
**Replacing a connection.** The replacement must be the same adaptor type (422 otherwise), and for HTTP it should reach the same application: each step keeps its relative URI, which was written for the old connection's API, so a swap between HTTP connections on different connectors breaks every step on its first run -- change each step's connection and endpoint together instead. Replacing a connection on a flow, or on one e...
© celigo · MIT · celigo/ai