Skip to content
Talk to an Engineer Dashboard

Connected accounts

Learn how to manage connected accounts in Agent Auth, including user authentication, authorization status, and account lifecycle management.

Connected accounts in Agent Auth represent individual user or organization connections to third-party providers. They contain the authentication state, tokens, and permissions needed to execute tools on behalf of a specific identifier (user_id, org_id, or custom identifier).

Connected accounts are the runtime instances that link your users to their third-party application accounts. Each connected account:

  • Links to a connection: Uses a pre-configured connection for authentication
  • Has a unique identifier: Associated with a user_id, org_id, or custom identifier
  • Maintains auth state: Tracks whether the user has completed authentication
  • Stores tokens: Securely holds access tokens and refresh tokens
  • Manages permissions: Tracks granted scopes and permissions

Connected accounts go through several states during their lifecycle:

  1. Pending: Account created but user hasn’t completed authentication
  2. Active: User has authenticated and tokens are valid
  3. Expired: Tokens have expired and need refresh
  4. Revoked: User has revoked access to the application
  5. Error: Account has authentication or configuration errors
  6. Suspended: Account temporarily disabled
PendingActiveExpiredRevokedErrorSuspended
  1. Navigate to connected accounts in your Agent Auth dashboard
  2. Click create account to start the process
  3. Select connection to use for authentication
  4. Enter identifier (user_id, email, or custom identifier)
  5. Configure settings such as scopes and permissions
  6. Generate auth URL for the user to complete authentication
  7. Monitor status until user completes the flow

Create connected accounts programmatically:

Terminal window
curl -X POST "https://api.scalekit.com/v1/connect/accounts" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"connection_id": "conn_gmail_oauth",
"identifier": "user_123",
"identifier_type": "user_id",
"scopes": ["https://www.googleapis.com/auth/gmail.send"],
"settings": {
"auto_refresh": true,
"expires_in": 3600
}
}'

For OAuth connections, connected accounts follow the standard OAuth flow:

  1. Create connected account with pending status
  2. Generate authorization URL for the user
  3. User completes OAuth flow with the third-party provider
  4. Provider redirects back with authorization code
  5. Exchange code for tokens and update account status
  6. Account becomes active and ready for tool execution

Generate URLs for users to complete authentication:

// Generate authorization URL
const authUrl = await agentConnect.accounts.getAuthUrl('account_id', {
state: 'custom_state_value',
redirect_uri: 'https://your-app.com/callback',
scopes: ['additional_scope']
});
// Example generated URL
// https://accounts.google.com/oauth/authorize?
// client_id=your_client_id&
// redirect_uri=https://your-app.com/callback&
// scope=https://www.googleapis.com/auth/gmail.send&
// response_type=code&
// state=custom_state_value

Process the OAuth callback to complete authentication:

// Handle OAuth callback
app.get('/callback', async (req, res) => {
const { code, state, error } = req.query;
if (error) {
// Handle OAuth error
return res.status(400).json({ error: error });
}
try {
// Exchange code for tokens
const result = await agentConnect.accounts.exchangeCode(
'account_id',
code,
state
);
// Account is now active
res.json({ status: 'success', account: result });
} catch (err) {
res.status(500).json({ error: err.message });
}
});

Retrieve connected account details:

const account = await agentConnect.accounts.get('account_id');
// Account object structure
{
"id": "account_123",
"connection_id": "conn_gmail_oauth",
"identifier": "user_123",
"identifier_type": "user_id",
"provider": "gmail",
"status": "active",
"scopes": ["https://www.googleapis.com/auth/gmail.send"],
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T10:45:00Z",
"expires_at": "2024-01-15T11:45:00Z",
"metadata": {
"user_email": "user@example.com",
"provider_account_id": "google_user_123"
}
}

Connected accounts automatically handle token lifecycle:

Automatic token refresh:

  • Tokens are refreshed automatically before expiration
  • Refresh happens transparently during tool execution
  • Failed refresh attempts update account status to expired

Manual token refresh:

// Manually refresh tokens
const refreshed = await agentConnect.accounts.refreshTokens('account_id');
// Check token status
const tokenStatus = await agentConnect.accounts.getTokenStatus('account_id');

Monitor account authentication status:

// Check account status
const status = await agentConnect.accounts.getStatus('account_id');
// Possible status values:
// - pending: Waiting for user authentication
// - active: Authenticated and ready
// - expired: Tokens expired, needs refresh
// - revoked: User revoked access
// - error: Authentication error
// - suspended: Account temporarily disabled

Scopes define what actions a connected account can perform on a user’s behalf. Understanding how scopes are configured and updated is critical to building reliable agent integrations.

Scopes are configured at the connection level, not at the individual connected account level. When a user completes the OAuth authorization flow for a connected account, they approve exactly the scopes defined on that connection.

Scopes are read-only after a connected account is created. There is no API or SDK method to modify the granted scopes on an existing connected account after the user has completed authentication.

To request additional scopes for an existing connected account:

  1. Update the connection configuration — In the Scalekit dashboard, navigate to the connection and add the new scopes.

  2. Generate a new magic link — Use the Scalekit dashboard or API to create a new authorization link for the user.

  3. User approves the updated consent screen — The user visits the link and approves the expanded OAuth consent screen with the new scopes.

  4. Connected account is updated — After the user approves, Scalekit updates the connected account with the new token set.

The user must go through the OAuth flow again whenever scopes change. There is no way to silently add scopes on their behalf.

When working with connected accounts, you may encounter the following enum values from the Scalekit platform:

Connector status

ValueDescription
CONNECTOR_STATUS_ACTIVEConnector is configured and operational
CONNECTOR_STATUS_INACTIVEConnector is configured but not active
CONNECTOR_STATUS_PENDINGConnector setup is incomplete
CONNECTOR_STATUS_ERRORConnector has a configuration or authentication error

Connector type

ValueDescription
CONNECTOR_TYPE_OAUTH2OAuth 2.0 connection (e.g., Gmail, Slack, GitHub)
CONNECTOR_TYPE_API_KEYAPI key-based connection (e.g., Zendesk, HubSpot)
CONNECTOR_TYPE_BASIC_AUTHUsername and password connection

These values are returned in API responses when listing or inspecting connections and connected accounts.

Store additional information with connected accounts:

// Add custom metadata
await agentConnect.accounts.updateMetadata('account_id', {
user_email: 'user@example.com',
department: 'engineering',
preferences: {
notification_settings: 'email',
timezone: 'UTC'
}
});
// Retrieve metadata
const metadata = await agentConnect.accounts.getMetadata('account_id');

Configure account-specific settings:

// Update account settings
await agentConnect.accounts.updateSettings('account_id', {
auto_refresh: true,
rate_limit: 100,
timeout: 30,
retry_attempts: 3
});

Handle multiple connected accounts efficiently:

// Create multiple accounts
const accounts = await agentConnect.accounts.createBulk([
{
connection_id: 'conn_gmail_oauth',
identifier: 'user_1',
identifier_type: 'user_id'
},
{
connection_id: 'conn_gmail_oauth',
identifier: 'user_2',
identifier_type: 'user_id'
}
]);
// Get accounts by connection
const gmailAccounts = await agentConnect.accounts.list({
connection_id: 'conn_gmail_oauth'
});
// Get accounts by status
const activeAccounts = await agentConnect.accounts.list({
status: 'active'
});

Perform operations on multiple accounts:

// Refresh tokens for multiple accounts
const refreshResults = await agentConnect.accounts.refreshTokensBulk([
'account_1',
'account_2',
'account_3'
]);
// Update settings for multiple accounts
await agentConnect.accounts.updateSettingsBulk([
'account_1',
'account_2'
], {
auto_refresh: true,
rate_limit: 150
});

Handle common connected account errors:

try {
const account = await agentConnect.accounts.get('account_id');
} catch (error) {
switch (error.code) {
case 'ACCOUNT_NOT_FOUND':
// Account doesn't exist
break;
case 'ACCOUNT_EXPIRED':
// Tokens expired, refresh needed
break;
case 'ACCOUNT_REVOKED':
// User revoked access
break;
case 'INVALID_PERMISSIONS':
// Insufficient permissions
break;
default:
// Other errors
break;
}
}

Implement error recovery strategies:

  1. Detect error - Monitor account status and API responses
  2. Classify error - Determine if error is recoverable
  3. Attempt recovery - Try token refresh or re-authentication
  4. Notify user - Inform user if manual action is required
  5. Update status - Update account status based on recovery result

Protect user tokens and credentials:

  • Encryption: All tokens are encrypted at rest and in transit
  • Token rotation: Implement regular token rotation
  • Access logging: Log all token access and usage
  • Secure storage: Use secure storage mechanisms for tokens

Follow principle of least privilege:

  • Minimal scopes: Request only necessary permissions
  • Scope validation: Verify permissions before tool execution
  • Regular audit: Review granted permissions regularly
  • User consent: Ensure users understand granted permissions

Ensure proper account isolation:

  • Tenant isolation: Separate accounts by tenant/organization
  • User isolation: Prevent cross-user data access
  • Connection isolation: Separate different connection types
  • Audit trail: Maintain detailed audit logs

Monitor connected account health:

// Get account health metrics
const health = await agentConnect.accounts.getHealth('account_id');
// Health metrics include:
// - Token expiry status
// - Authentication success rate
// - API error rates
// - Last successful authentication

Track account usage patterns:

// Get account usage statistics
const usage = await agentConnect.accounts.getUsage('account_id', {
start_date: '2024-01-01',
end_date: '2024-01-31'
});
// Usage data includes:
// - Total tool executions
// - API requests made
// - Error rates
// - Most used tools
  • Regular cleanup: Remove unused or expired accounts
  • Status monitoring: Monitor account status changes
  • Proactive refresh: Refresh tokens before expiration
  • User notifications: Notify users of authentication issues
  • Connection pooling: Reuse connections efficiently
  • Token caching: Cache tokens appropriately
  • Batch operations: Use bulk operations when possible
  • Async processing: Handle authentication flows asynchronously
  • Clear error messages: Provide helpful error messages to users
  • Seamless re-auth: Make re-authentication flows smooth
  • Status visibility: Show users their connection status
  • Easy revocation: Allow users to easily revoke access

Test connected accounts in development:

// Create test account
const testAccount = await agentConnect.accounts.create({
connection_id: 'conn_test_provider',
identifier: 'test_user',
identifier_type: 'user_id',
test_mode: true
});
// Use test tokens
const testTokens = await agentConnect.accounts.getTestTokens('account_id');

Test authentication flows:

  1. Create test connection with test credentials
  2. Create connected account with test identifier
  3. Generate auth URL and complete OAuth flow
  4. Verify account status becomes active
  5. Test tool execution with the account
  6. Test token refresh and error scenarios

Next, learn how to execute tools using your connected accounts to interact with third-party applications.