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

# 接続

> OAuth を介して、アプリがユーザーに代わってサードパーティのサービスで操作を行えるようにします。

接続（Connection）は、ユーザーが外部サービス（Linear、GitHub、Slack など）のために保持する認証情報です。 あなたのアプリは、それらの認証情報を**どのように**取得するか — **接続プロバイダー** — を宣言し、実行時にそれらを利用してサードパーティの API へ認証付きの呼び出しを行います。

現在は OAuth 2.0 のみサポートされています。 将来的な認証情報タイプ（パーソナルアクセストークン、API キー、Basic 認証）も同じインターフェースに差し込まれます — すでに `defineConnectionProvider({ type: 'oauth', ... })` を使用しているアプリは移行の必要がありません。

<AccordionGroup>
  <Accordion title="defineConnectionProvider" description="アプリの接続をどのように取得するかを宣言する">
    接続プロバイダーは、アプリに必要な OAuth のハンドシェイクを記述します。 ユーザーがアプリの設定で"接続を追加"をクリックし、プロバイダーの同意画面を完了すると、そのワークスペースに `ConnectedAccount` の行が作成されます。

    動作するセットアップには、**2 つのファイル**が必要です — 接続プロバイダーと、OAuth クライアント認証情報を保持する `defineApplication` 上の対応する `serverVariables` 宣言です。

    ```ts src/connection-providers/linear-connection.ts theme={null}
    import { defineConnectionProvider } from 'twenty-sdk/define';

    export default defineConnectionProvider({
      universalIdentifier: '9c7d1f5e-6a0b-4d44-be0c-3f8b5a9d4e6f',
      name: 'linear',
      displayName: 'Linear',
      icon: 'IconBrandLinear',
      type: 'oauth',
      oauth: {
        authorizationEndpoint: 'https://linear.app/oauth/authorize',
        tokenEndpoint: 'https://api.linear.app/oauth/token',
        scopes: ['read', 'write'],
        // These must match keys in `defineApplication.serverVariables` below.
        clientIdVariable: 'LINEAR_CLIENT_ID',
        clientSecretVariable: 'LINEAR_CLIENT_SECRET',
        // Optional: defaults to 'json'. Some providers (Linear, Slack) want
        // 'form-urlencoded' for the token request.
        tokenRequestContentType: 'form-urlencoded',
        // Optional: defaults to true. Disable only if the provider rejects PKCE.
        usePkce: false,
        // Optional: extra query params on the authorize URL.
        // authorizationParams: { prompt: 'consent' },
        // Optional: provider's RFC 7009 token revocation endpoint, called on disconnect.
        // revokeEndpoint: 'https://example.com/oauth/revoke',
      },
    });
    ```

    ```ts src/application.config.ts theme={null}
    import { defineApplication } from 'twenty-sdk/define';

    export default defineApplication({
      universalIdentifier: '...',
      displayName: 'Linear',
      description: 'Connect Linear to Twenty.',
      // OAuth client credentials live on the app registration (one OAuth app per
      // Twenty server, configured by the admin) — not per-workspace. Declare them
      // as serverVariables so the admin can fill them in once for all installs.
      serverVariables: {
        LINEAR_CLIENT_ID: {
          description: 'OAuth client ID from your Linear OAuth application.',
          isSecret: false,
          isRequired: true,
        },
        LINEAR_CLIENT_SECRET: {
          description: 'OAuth client secret from your Linear OAuth application.',
          isSecret: true,
          isRequired: true,
        },
      },
    });
    ```

    主なポイント：

    * `listConnections({ providerName })` で使用される一意の識別子文字列が `name` です（kebab-case、`^[a-z][a-z0-9-]*$` に一致する必要があります）。
    * `displayName` はアプリごとの設定タブおよび AI ツール一覧に表示されます。
    * `clientIdVariable` / `clientSecretVariable` は値ではなく**名前**です — `defineApplication.serverVariables` で宣言されたキーと一致している必要があります。 実際の `client_id` と `client_secret` は、アプリ登録 UI を通じてサーバー管理者が入力し、あなたのリポジトリにコミットされることはありません。
    * `applicationVariables` ではなく `serverVariables` を使用してください — OAuth の認証情報はサーバー全体で共有され、Twenty サーバーごとに 1 つの OAuth アプリとなります。
    * 両方の `serverVariables` が入力されるまで、アプリごとの設定タブには"サーバー管理者が必要"というヒントが表示され、"接続を追加"ボタンは無効になります。
    * 現在サポートされる値は `type: 'oauth'` のみです。 この判別子は前方互換です。将来のタイプ（`'pat'`、`'api-key'`、...） は、`oauth` に並ぶ新しいサブ設定ブロックを追加します。

    プロバイダーで許可リストに登録する必要がある OAuth のコールバック URL は次のとおりです:

    ```
    https://<your-twenty-server>/auth/apps/callback
    ```
  </Accordion>

  <Accordion title="listConnections / getConnection" description="ロジック関数から接続を使用する">
    ロジック関数ハンドラー内では、`listConnections({ providerName })` が指定したプロバイダーに対するこのアプリの `ConnectedAccount` 行を、更新済みのアクセストークン付きで返します。

    ```ts src/logic-functions/handlers/create-linear-issue-handler.ts theme={null}
    import { listConnections } from 'twenty-sdk/logic-function';

    export const createLinearIssueHandler = async (input: {
      teamId?: string;
      title?: string;
    }) => {
      if (!input.teamId || !input.title) {
        return { success: false, error: 'teamId and title are required' };
      }

      const connections = await listConnections({ providerName: 'linear' });

      // Workspace-shared credentials win when present; fall back to the first
      // user-visibility one. For HTTP-route triggers you typically pick the
      // request user's connection via event.userWorkspaceId instead.
      const connection =
        connections.find((c) => c.visibility === 'workspace') ?? connections[0];

      if (!connection) {
        return {
          success: false,
          error:
            'Linear is not connected. Open the app settings and click "Add connection".',
        };
      }

      // Use connection.accessToken to call the third-party API.
      const response = await fetch('https://api.linear.app/graphql', {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${connection.accessToken}`,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          query: `mutation { issueCreate(input: { teamId: "${input.teamId}", title: "${input.title}" }) { success } }`,
        }),
      });

      return { success: response.ok };
    };
    ```

    各接続には次の項目があります:

    | フィールド             | 説明                                                         |
    | ----------------- | ---------------------------------------------------------- |
    | `id`              | 一意の行 ID。単一の接続を再取得するには `getConnection(id)` に渡します。           |
    | `visibility`      | `'user'`（ワークスペースの 1 メンバー専用）または `'workspace'`（全メンバーと共有）     |
    | `scopes`          | 連携先プロバイダーによって付与された OAuth 権限（`visibility` とは別で、無関係です）       |
    | `userWorkspaceId` | 所有者の userWorkspace ID — HTTP ルートトリガーで"要求ユーザーの接続"を選ぶのに役立ちます |
    | `accessToken`     | 新しい OAuth アクセストークン（期限切れの場合は自動更新）                           |
    | `name` / `handle` | 接続の表示名（OAuth コールバック時に自動取得。ユーザーが名称変更可能）                     |
    | `authFailedAt`    | 直近の更新に失敗した場合に設定されます。ユーザーは再接続する必要があります。                     |

    主なポイント：

    * プロバイダーで絞り込むには `{ providerName }` を渡します。省略すると、このアプリが保有するすべてのプロバイダーの接続を取得します。
    * サーバーは返却前にアクセストークンを透過的に更新します。 ハンドラーは常に利用可能なトークン（または `authFailedAt` が設定された状態）を受け取ります。
    * `getConnection(id)` は単一行の取得に相当します。
  </Accordion>

  <Accordion title="ユーザー単位 vs ワークスペース共有の可視性" description="ユーザーがプライベートと共有の認証情報を選ぶ方法">
    ユーザーが"接続を追加"をクリックすると、可視性の選択を求められます:

    * **自分だけ** — 認証情報は接続したユーザー専用です。 そのユーザーの権限で呼び出される任意のロジック関数（`isAuthRequired: true` の HTTP ルートトリガー）は参照できますが、cron トリガーやデータベースイベントは参照できません。
    * **ワークスペースで共有** — どのワークスペースメンバーでもその認証情報を使用できます。 リクエストユーザーを持たないため、Cron／データベースのトリガーからも参照されます。

    各ハンドラーで適切な方を使用してください:

    ```ts theme={null}
    // HTTP-route trigger — prefer the request user's own connection.
    const conn =
      connections.find((c) => c.userWorkspaceId === event.userWorkspaceId) ??
      connections.find((c) => c.visibility === 'workspace');

    // Cron trigger — no request user; only shared credentials are sensible.
    const conn = connections.find((c) => c.visibility === 'workspace');
    ```

    （ユーザー、プロバイダー）ごとに複数の接続が許可されているため、同一ユーザーが "Personal Linear" と "Work Linear" を並行して保持できます。
  </Accordion>

  <Accordion title="一度きりのプロバイダー設定" description="サードパーティサービスに OAuth アプリを登録する">
    各接続プロバイダーごとに、まずサーバー管理者がサードパーティ側で OAuth アプリを登録する必要があります。

    1. プロバイダーの開発者設定に移動します（例: [https://linear.app/settings/api/applications/new）。](https://linear.app/settings/api/applications/new）。)
    2. **Redirect URI** を `\<SERVER_URL>/auth/apps/callback` に設定します。
    3. 生成された **Client ID** と **Client Secret** をコピーします。
    4. サーバー管理者として Twenty でインストール済みアプリを開き、対応する `serverVariables` に値を設定します。
    5. その後、ワークスペースメンバーはアプリごとの **Connections** セクションから接続を追加できます。
  </Accordion>
</AccordionGroup>
