> ## 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.

# Connexions

> Autorisez votre application à agir au nom d'un utilisateur auprès de services tiers via OAuth.

Les connexions sont des identifiants qu'un utilisateur détient pour un service externe (Linear, GitHub, Slack, ...). Votre application déclare **comment** ces identifiants sont obtenus — un **fournisseur de connexion** — et les consomme à l'exécution pour effectuer des appels authentifiés vers l'API tierce.

À ce jour, seul OAuth 2.0 est pris en charge. De futurs types d'identifiants (jetons d'accès personnels, clés d'API, authentification de base) s'intégreront à la même interface — les applications utilisant déjà `defineConnectionProvider({ type: 'oauth', ... `})\` n'auront pas besoin de migrer.

<AccordionGroup>
  <Accordion title="defineConnectionProvider" description="Déclarez comment les connexions de votre application sont obtenues">
    Un fournisseur de connexion décrit le processus d'échange OAuth requis par votre application. L'utilisateur clique sur "Ajouter une connexion" dans les paramètres de votre application, complète l'écran de consentement du fournisseur, et une ligne `ConnectedAccount` est créée dans son espace de travail.

    Une configuration fonctionnelle nécessite **deux fichiers** — le fournisseur de connexion, et une déclaration `serverVariables` correspondante sur `defineApplication` qui contient les identifiants client OAuth.

    ```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',
      },
      // Optional: a logic function in this app to run right after a connection is
      // established. See "Run a logic function on connect".
      // onConnectLogicFunction: { universalIdentifier: '3a2b1c0d-...-...' },
    });
    ```

    ```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,
        },
      },
    });
    ```

    Points clés :

    * `name` est l'identifiant unique utilisé dans `listConnections({ providerName })` (kebab-case, doit correspondre à `^[a-z][a-z0-9-]*$`).
    * `displayName` s'affiche dans l'onglet des paramètres par application et dans la liste des outils d'IA.
    * `clientIdVariable` / `clientSecretVariable` sont des **noms**, pas des valeurs — ils doivent correspondre aux clés déclarées dans `defineApplication.serverVariables`. Les `client_id` et `client_secret` réels sont saisis par l'administrateur du serveur via l'interface d'enregistrement de l'application, et ne sont jamais validés dans votre dépôt.
    * Utilisez `serverVariables` (pas `applicationVariables`) — les identifiants OAuth sont au niveau du serveur et il n'y a qu'une application OAuth par serveur Twenty.
    * Tant que les deux `serverVariables` ne sont pas renseignées, l'onglet des paramètres par application affiche une indication "nécessite un administrateur du serveur" et le bouton "Ajouter une connexion" est désactivé.
    * `type: 'oauth'` est la seule valeur prise en charge à ce jour. Le discriminateur est compatible avec les évolutions : des types futurs (`'pat'`, `'api-key'`, ...) ajouteront de nouveaux blocs de sous-configuration à côté de `oauth`.

    L'URL de rappel OAuth que votre fournisseur doit autoriser est :

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

  <Accordion title="Exécuter une fonction logique lors de la connexion" description="Réagir au moment où une connexion est établie">
    Certains fournisseurs vous transmettent, au moment de la connexion, des données que vous devez conserver avant que la connexion ne soit exploitable — l’exemple classique est Slack, où la réponse OAuth identifie le `team_id` de l’espace de travail sur lequel les événements entrants seront indexés. Définissez `onConnectLogicFunction` pour référencer une fonction logique dans la même application (par son `universalIdentifier`), et elle s’exécute juste après la création du `ConnectedAccount`.

    ```ts src/connection-providers/slack-connection.ts theme={null}
    export default defineConnectionProvider({
      universalIdentifier: '...',
      name: 'slack',
      displayName: 'Slack',
      type: 'oauth',
      oauth: {
        /* ... */
      },
      // Runs claimSlackTeam after every successful Slack connection.
      onConnectLogicFunction: {
        universalIdentifier: '3a2b1c0d-1111-4222-8333-444455556666',
      },
    });
    ```

    Le hook s’exécute **de manière asynchrone dans l’espace de travail en cours de connexion** (il est mis en file d’attente, non attendu), de sorte qu’un hook lent ou défaillant ne bloque ni n’interrompt jamais le callback OAuth — rendez-le idempotent et faites en sorte qu’il gère ses propres réessais. Le gestionnaire reçoit :

    ```ts theme={null}
    type OnConnectPayload = {
      connectionProviderId: string;
      connectionProviderName: string; // e.g. 'slack'
      connectedAccountId: string;
    };
    ```

    À partir de là, utilisez `getConnection(connectedAccountId)` pour lire le jeton d’accès actualisé et appeler l’API du fournisseur (par exemple Slack `auth.test`) ou persister un mappage dans le [stockage clé-valeur](/l/fr/developers/extend/apps/logic/key-value-store).
  </Accordion>

  <Accordion title="listConnections / getConnection" description="Utilisez les connexions depuis une fonction logique">
    Dans un gestionnaire de fonction logique, `listConnections({ providerName })` renvoie les lignes `ConnectedAccount` de cette application pour le fournisseur donné, avec des jetons d'accès actualisés.

    ```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 };
    };
    ```

    Chaque connexion comporte :

    | Champ             | Description                                                                                                                                     |
    | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
    | `id`              | ID de ligne unique ; à passer à `getConnection(id)` pour en récupérer une seule                                                                 |
    | `visibility`      | `'user'` (réservée à un membre de l'espace de travail) ou `'workspace'` (partagée avec tous les membres)                                        |
    | `scopes`          | Autorisations OAuth accordées par le fournisseur en amont (distinctes de `visibility` — sans rapport)                                           |
    | `userWorkspaceId` | L'ID userWorkspace du propriétaire — utile pour sélectionner "la connexion de l'utilisateur de la requête" dans les déclencheurs de routes HTTP |
    | `accessToken`     | Jeton d'accès OAuth à jour (actualisé automatiquement s'il a expiré)                                                                            |
    | `name` / `handle` | Le nom d'affichage de la connexion (déduit automatiquement lors du callback OAuth, renommable par l'utilisateur)                                |
    | `authFailedAt`    | Défini lorsque le rafraîchissement le plus récent a échoué ; l'utilisateur doit se reconnecter                                                  |

    Points clés :

    * Passez `{ providerName }` pour filtrer par fournisseur ; omettez-le pour obtenir toutes les connexions que cette application possède sur l'ensemble des fournisseurs.
    * Le serveur actualise de manière transparente le jeton d'accès avant de répondre. Votre gestionnaire voit toujours un jeton utilisable (ou `authFailedAt` défini).
    * `getConnection(id)` est l'équivalent pour une seule ligne.
  </Accordion>

  <Accordion title="Visibilité par utilisateur vs partagée à l'échelle de l'espace de travail" description="Comment les utilisateurs choisissent entre des identifiants privés et partagés">
    Lorsqu'un utilisateur clique sur "Ajouter une connexion", il lui est demandé de choisir une visibilité :

    * **Uniquement pour moi** — les identifiants sont privés pour l'utilisateur qui se connecte. Toute fonction logique appelée en son nom (déclencheur de route HTTP avec `isAuthRequired: true`) y a accès ; les déclencheurs cron et les événements de base de données n'y ont pas accès.
    * **Partagé au niveau de l'espace de travail** — tout membre de l'espace de travail peut utiliser les identifiants. Les déclencheurs cron / base de données y ont également accès, puisqu'ils n'ont pas d'utilisateur de requête.

    Utilisez le bon pour chaque gestionnaire :

    ```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');
    ```

    Plusieurs connexions par (utilisateur, fournisseur) sont autorisées, ainsi le même utilisateur peut avoir "Linear personnel" et "Linear professionnel" côte à côte.
  </Accordion>

  <Accordion title="Configuration unique du fournisseur" description="Enregistrez votre application OAuth auprès du service tiers">
    Pour chaque fournisseur de connexion, l'administrateur du serveur doit d'abord enregistrer une application OAuth auprès du service tiers.

    1. Accédez aux paramètres développeur du fournisseur (par ex. [https://linear.app/settings/api/applications/new](https://linear.app/settings/api/applications/new)).
    2. Définissez l'**URI de redirection** sur `\<SERVER_URL>/auth/apps/callback`.
    3. Copiez l'**ID client** et le **Secret client** générés.
    4. Ouvrez l'application installée dans Twenty en tant qu'administrateur du serveur → définissez les valeurs sur les `serverVariables` correspondantes.
    5. Les membres de l'espace de travail peuvent ensuite ajouter des connexions depuis la section **Connexions** par application.
  </Accordion>
</AccordionGroup>
