defineConnectionProvider({ type: 'oauth', ... }) won’t need to migrate.
defineConnectionProvider
Declare how your app's connections are obtained
defineConnectionProvider
Declare how your app's connections are obtained
A connection provider describes the OAuth handshake your app needs. The user clicks “Add connection” in your app’s settings, completes the provider’s consent screen, and a Key points:
ConnectedAccount row is created in their workspace.A working setup needs two files — the connection provider, and a matching serverVariables declaration on defineApplication that holds the OAuth client credentials.src/connection-providers/linear-connection.ts
src/application.config.ts
nameis the unique identifier string used inlistConnections({ providerName })(kebab-case, must match^[a-z][a-z0-9-]*$).displayNameshows in the per-app settings tab and in the AI tool list.clientIdVariable/clientSecretVariableare names, not values — they must match keys declared indefineApplication.serverVariables. The actualclient_idandclient_secretare entered by the server admin through the app registration UI, never committed to your repo.- Use
serverVariables(notapplicationVariables) — OAuth credentials are server-wide and one OAuth app per Twenty server. - Until both
serverVariablesare filled in, the per-app settings tab shows a “needs server admin” hint and the “Add connection” button is disabled. type: 'oauth'is the only supported value today. The discriminator is forward-compatible: future types ('pat','api-key', …) will add new sub-config blocks alongsideoauth.
Run a logic function on connect
React the moment a connection is established
Run a logic function on connect
React the moment a connection is established
Some providers hand you data at connect time that you need to persist before the connection is usable — the classic example is Slack, where the OAuth response identifies the workspace’s The hook runs asynchronously in the connecting workspace (it is enqueued, not awaited), so a slow or failing hook never blocks or breaks the OAuth callback — make it idempotent and handle its own retries. The handler receives:From there use
team_id that inbound events will be keyed by. Set onConnectLogicFunction to reference a logic function in the same app (by its universalIdentifier), and it runs right after the ConnectedAccount is created.src/connection-providers/slack-connection.ts
getConnection(connectedAccountId) to read the fresh access token and call the provider’s API (e.g. Slack auth.test) or persist a mapping with the key-value store.listConnections / getConnection
Use connections from a logic function
listConnections / getConnection
Use connections from a logic function
Inside a logic function handler, Each connection has:
listConnections({ providerName }) returns this app’s ConnectedAccount rows for the given provider, with refreshed access tokens.src/logic-functions/handlers/create-linear-issue-handler.ts
Key points:
- Pass
{ providerName }to filter by provider; omit it to get all connections this app owns across all providers. - The server transparently refreshes the access token before returning. Your handler always sees a usable token (or
authFailedAtset). getConnection(id)is the single-row equivalent.
How users choose between private and shared credentials
How users choose between private and shared credentials
One-time provider setup
Register your OAuth app with the third-party service
One-time provider setup
Register your OAuth app with the third-party service
For each connection provider, the server admin needs to register an OAuth app at the third party first.
- Go to the provider’s developer settings (e.g. https://linear.app/settings/api/applications/new).
- Set the Redirect URI to
<SERVER_URL>/auth/apps/callback. - Copy the generated Client ID and Client Secret.
- Open the installed app in Twenty as a server admin → set the values on the corresponding
serverVariables. - Workspace members can then add connections from the per-app Connections section.