Manage connected accounts
Check status, list, delete, and update credentials for connected accounts across all connector auth types.
A connected account is the per-user record that holds a user’s credentials and tracks their authorization state for a specific connection. Scalekit creates one automatically when a user completes authentication.
Account states
Section titled “Account states”| State | Meaning |
|---|---|
ACTIVE | Credentials valid, ready for tool calls |
EXPIRED | Access token expired and needs refresh or re-authentication |
PENDING_AUTH | User hasn’t completed authentication, or re-authentication is in progress |
PENDING_VERIFICATION | OAuth complete; user identity verification still required before activation |
DISCONNECTED | Account was manually disconnected |
See Troubleshoot connection errors for what to do in each state.
Check account status
Section titled “Check account status”Use get_or_create_connected_account as the safe default when a user may be connecting for the first time. Use get_connected_account only when you know the account already exists and you need to inspect or return its stored auth details.
response = actions.get_or_create_connected_account( connection_name="gmail", identifier="user_123")connected_account = response.connected_accountprint(f"Status: {connected_account.status}")const response = await actions.getOrCreateConnectedAccount({ connectionName: 'gmail', identifier: 'user_123',});
console.log('Status:', response.connectedAccount?.status);Handle inactive accounts
Section titled “Handle inactive accounts”When a connected account isn’t ACTIVE, generate a new authorization link and send it to the user.
The link opens a Hosted Page, a Scalekit-hosted UI that adapts automatically based on the connection’s auth type:
- OAuth connectors: presents the provider’s OAuth consent screen
- API key, basic auth, or other connectors: presents a form to collect the required credentials
Your code is the same regardless of connector type. Scalekit determines the right flow based on the connection configuration.
if connected_account.status != "ACTIVE": link_response = actions.get_authorization_link( connection_name="gmail", identifier="user_123" ) # Redirect or send link_response.link to the userimport { ConnectorStatus } from '@scalekit-sdk/node/lib/pkg/grpc/scalekit/v1/connected_accounts/connected_accounts_pb';
if (connectedAccount?.status !== ConnectorStatus.ACTIVE) { const linkResponse = await actions.getAuthorizationLink({ connectionName: 'gmail', identifier: 'user_123', }); // Redirect or send linkResponse.link to the user}Detect when re-authentication is needed
Section titled “Detect when re-authentication is needed”A connected account can leave the ACTIVE state on its own, with no action from you or the user. When that happens, the next tool call fails until the user re-authorizes. To catch it early, subscribe to the connected_account.status_updated webhook instead of waiting for a failed call.
Common causes
Section titled “Common causes”OAuth connected accounts most often move to EXPIRED for reasons outside Scalekit’s control:
- The provider revoked the refresh token. A password change, an admin-initiated token revocation, or a provider security policy invalidates the refresh token, so Scalekit can no longer obtain new access tokens.
- The refresh token expired. Providers cap refresh-token lifetimes (for example, 30 or 180 days), and the expiry is rarely surfaced in advance.
- No refresh token was issued. When the connection’s scopes don’t request offline access, the provider returns only a short-lived access token and no refresh token to renew it.
- The provider hit a per-user token limit. Some providers keep only a fixed number of refresh tokens per user and app, and silently drop the oldest ones when a user reconnects repeatedly.
The first two cases require the user to re-authenticate; there is no server-side workaround. The last two are configuration issues you fix on the connection by requesting offline access scopes.
Subscribe to status changes
Section titled “Subscribe to status changes”The connected_account.status_updated event fires on every status transition and carries both the new and previous status:
{ "spec_version": "1", "id": "evt_101652975398683158", "type": "connected_account.status_updated", "occurred_at": "2025-12-02T06:31:34.895815554Z", "environment_id": "env_88640229614813449", "object": "ConnectedAccount", "data": { "id": "ca_133400349586228019", "identifier": "john@acmecorp.com", "connection_id": "conn_133400101014995480", "connection_name": "gmail", "provider": "GMAIL", "authorization_type": "OAUTH", "status": "EXPIRED", "old_status": "ACTIVE" }}Because the event covers every transition, filter on the change you care about. To alert users only when an active account needs re-authorization, act on old_status ACTIVE moving to status EXPIRED:
// The event fires for all transitions (for example, PENDING_AUTH to ACTIVE).// Filter to the one that requires user action, or you will notify on noise.if (event.data.old_status === 'ACTIVE' && event.data.status === 'EXPIRED') { // Generate a fresh authorization link and notify the user}When you receive this event, generate a new authorization link and prompt the user to reconnect. See the full payload for the connected_account.status_updated event in the API reference.
List connected accounts
Section titled “List connected accounts”const listResponse = await actions.listConnectedAccounts({ connectionName: 'gmail',});console.log('Connected accounts:', listResponse);Delete a connected account
Section titled “Delete a connected account”Deleting a connected account removes the user’s credentials and authorization state. The user must re-authenticate to reconnect.
await actions.deleteConnectedAccount({ connectionName: 'gmail', identifier: 'user_123',});Update OAuth scopes
Section titled “Update OAuth scopes”Scopes apply to OAuth connectors only. For non-OAuth connectors (API key, basic auth, and similar), generate a new authorization link and the hosted page will collect updated credentials.
To request additional OAuth scopes from an existing connected account:
- Update the connection’s scopes in AgentKit > Connections > Edit.
- Generate a new authorization link for the user.
- The user completes the OAuth consent screen, approving the updated scopes.
- Scalekit updates the connected account with the new token set.