Skip to content

Connected accounts

When an agent connects a third-party account (see Connecting an account), it can read that account’s credentials through the agent API to make calls on the user’s behalf. This is what an integration’s tools use under the hood; you can use the same methods when building your own.

All examples use the @alfe.ai/agent-api-client. Every method resolves against the accounts in the agent’s own scope — an agent can only read credentials for accounts it has access to.

A single agent can connect more than one account for the same provider — two GitHub logins, several Xero organizations, multiple Google accounts. The get<Provider>Accounts() methods return every connected account for that provider, each with a stable identifier you use to pick one:

connected-accounts.ts
const { accounts } = await client.getGithubAccounts();
// GET /agent/connect/github/accounts
for (const a of accounts) {
console.log(a.login, a.accessToken); // pick the account by its `login`
}
{
"data": {
"accounts": [
{
"connectionId": "con_…",
"accountIdentifier": "octocat",
"login": "octocat",
"displayName": "The Octocat",
"accessToken": "gho_…",
"scopes": "repo,read:org",
"connectedAt": "2026-06-01T00:00:00.000Z"
}
]
}
}

The stable per-account selector differs by provider — for GitHub it’s login, for Salesforce it’s the organization id, for Notion the workspace id, and for Google and Microsoft the account email. Xero exposes two distinct identifiers: use xeroTenantId to select the organization in tools, and use accountIdentifier only when calling the refresh helper. When you build a tool that touches an account, require its provider selector as an argument so the account is always chosen deliberately.

Xero organization selection is currently fail-closed: a credential is usable by the Xero MCP integration only when it exposes exactly one organization. OAuth grants spanning several organizations remain visible but require a future organization-selection flow before tools can use them.

Provider Accounts (multi) Refresh (per account)
GitHub getGithubAccounts() — (tokens don’t expire)
Google getGoogleCredentials() (returns accounts)
Xero getXeroAccounts() refreshXeroAccountToken(accountIdentifier)
Notion getNotionAccounts()
Atlassian getAtlassianAccounts() refreshAtlassianAccountToken(email)
MYOB getMYOBAccounts() refreshMYOBAccountToken(accountIdentifier)
Salesforce getSalesforceAccounts() refreshSalesforceAccountToken(orgId)
Microsoft 365 getMicrosoftAccounts() refreshMicrosoftAccountToken(id)

Each get…Accounts() method returns the fields that provider’s API needs — for example Xero and Salesforce include accessTokenExpiresAt, Salesforce also includes instanceUrl, Atlassian includes the list of accessible sites (availableSites), and Google includes the OAuth client id and secret.

Providers whose access tokens expire expose a per-account refresh method. Target the specific account by its stable identifier — tokens aren’t interchangeable across accounts:

const { accessToken, accessTokenExpiresAt } =
await client.refreshXeroAccountToken(account.accountIdentifier);
// POST /agent/connect/xero/accounts/{accountIdentifier}/refresh

GitHub tokens don’t expire, so there is no GitHub refresh method — if a token is revoked, re-run the connect flow.

If you already know a connection’s stable connectionId (for example from listIntegrations() or a get…Accounts() result), you can fetch just that connection’s credentials:

const creds = await client.getConnectionCredentials("con_…");
// GET /agent/connect/connections/{connectionId}/credentials

The endpoint enforces that the connection is in the calling agent’s scope, so a connection the agent can’t see comes back as forbidden.

The values returned here are live access tokens and, for some providers, OAuth client secrets. Use them to make the API call you need and don’t persist or log them — request them again when you need them next. See Connecting an account for how accounts are authorized in the first place.