Saltar al contenido principal
Las conexiones son credenciales que un usuario posee para un servicio externo (Linear, GitHub, Slack, …). Tu aplicación declara cómo se obtienen esas credenciales — un proveedor de conexión — y las consume en tiempo de ejecución para realizar llamadas autenticadas a la API de terceros. Actualmente solo se admite OAuth 2.0. Los futuros tipos de credenciales (tokens de acceso personal, claves de API, autenticación básica) se integrarán en la misma interfaz — las aplicaciones que ya usan defineConnectionProvider({ type: 'oauth', ... }) no necesitarán migrar.
Un proveedor de conexión describe el flujo de OAuth que tu aplicación necesita. El usuario hace clic en “Agregar conexión” en la configuración de tu aplicación, completa la pantalla de consentimiento del proveedor y se crea una fila ConnectedAccount en su espacio de trabajo.Una configuración funcional necesita dos archivos — el proveedor de conexión y una declaración serverVariables correspondiente en defineApplication que contiene las credenciales del cliente OAuth.
src/connection-providers/linear-connection.ts
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',
  },
});
src/application.config.ts
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,
    },
  },
});
Puntos clave:
  • name es la cadena de identificador única utilizada en listConnections({ providerName }) (kebab-case, debe coincidir con ^[a-z][a-z0-9-]*$).
  • displayName se muestra en la pestaña de configuración por aplicación y en la lista de herramientas de IA.
  • clientIdVariable / clientSecretVariable son nombres, no valores — deben coincidir con las claves declaradas en defineApplication.serverVariables. Los client_id y client_secret reales los introduce el administrador del servidor a través de la interfaz de registro de la aplicación; nunca se incluyen en tu repositorio.
  • Usa serverVariables (no applicationVariables) — las credenciales de OAuth son a nivel de servidor y hay una aplicación OAuth por servidor de Twenty.
  • Hasta que ambos serverVariables estén completos, la pestaña de configuración por aplicación muestra un aviso de “requiere administrador del servidor” y el botón “Agregar conexión” está deshabilitado.
  • type: 'oauth' es el único valor admitido actualmente. El discriminador es compatible hacia adelante: tipos futuros ('pat', 'api-key', …) agregarán nuevos bloques de subconfiguración junto a oauth.
La URL de callback de OAuth que tu proveedor debe autorizar es:
https://<your-twenty-server>/auth/apps/callback
Dentro de un controlador de función de lógica, listConnections({ providerName }) devuelve las filas ConnectedAccount de esta aplicación para el proveedor indicado, con tokens de acceso actualizados.
src/logic-functions/handlers/create-linear-issue-handler.ts
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 };
};
Cada conexión tiene:
CampoDescripción
idID de fila único; pásalo a getConnection(id) para volver a obtener una sola conexión
visibility'user' (privada para un miembro del espacio de trabajo) o 'workspace' (compartida con todos los miembros)
scopesPermisos de OAuth concedidos por el proveedor de origen (distintos de visibility — no están relacionados)
userWorkspaceIdEl id de userWorkspace del propietario — útil para elegir “la conexión del usuario de la solicitud” en activadores de rutas HTTP
accessTokenToken de acceso OAuth actualizado (se renueva automáticamente si ha expirado)
name / handleEl nombre para mostrar de la conexión (derivado automáticamente en el callback de OAuth, el usuario puede cambiarlo)
authFailedAtSe establece cuando la actualización más reciente falló; el usuario debe reconectarse
Puntos clave:
  • Pasa { providerName } para filtrar por proveedor; omítelo para obtener todas las conexiones que posee esta aplicación en todos los proveedores.
  • El servidor actualiza de forma transparente el token de acceso antes de devolver la respuesta. Tu controlador siempre ve un token utilizable (o authFailedAt establecido).
  • getConnection(id) es el equivalente de una sola fila.
Cuando un usuario hace clic en “Agregar conexión”, se le solicita que elija una visibilidad:
  • Solo para mí — la credencial es privada para el usuario que se conecta. Cualquier función de lógica llamada en su nombre (activador de ruta HTTP con isAuthRequired: true) la ve; los activadores de cron y los eventos de base de datos no.
  • Compartida en el espacio de trabajo — cualquier miembro del espacio de trabajo puede usar la credencial. Los activadores de cron y de base de datos también la ven, ya que no tienen usuario de la solicitud.
Usa la adecuada para cada controlador:
// 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');
Se permiten múltiples conexiones por (usuario, proveedor), por lo que el mismo usuario puede tener “Linear personal” y “Linear de trabajo” a la vez.
Para cada proveedor de conexión, el administrador del servidor debe registrar primero una aplicación OAuth en el servicio de terceros.
  1. Ve a la configuración de desarrollador del proveedor (p. ej., https://linear.app/settings/api/applications/new).
  2. Configura el URI de redirección en \<SERVER_URL>/auth/apps/callback.
  3. Copia el Client ID y el Client Secret generados.
  4. Abre la aplicación instalada en Twenty como administrador del servidor → establece los valores en los serverVariables correspondientes.
  5. Luego, los miembros del espacio de trabajo pueden agregar conexiones desde la sección Conexiones por aplicación.