Skip to main content
The Accounts API manages OAuth connections to external services like Google, GitHub, and Notion. These accounts enable widgets to access user data from integrated services.

Supported Providers

  • google - Google OAuth integration
  • github - GitHub OAuth integration
  • notion - Notion OAuth integration

Get Connected Accounts

Retrieve all connected OAuth accounts for the authenticated user.
curl -X GET http://localhost:3000/api/accounts \
  -H "Cookie: session=your-session-token"

Response

Returns an array of connected account objects.
id
string
Unique account identifier
accountId
string
Provider-specific account ID
providerId
string
OAuth provider: google, github, or notion
userId
string
ID of the user who connected this account
accessToken
string | null
OAuth access token (sensitive - handle with care)
refreshToken
string | null
OAuth refresh token (sensitive - handle with care)
idToken
string | null
OpenID Connect ID token
accessTokenExpiresAt
string (ISO 8601) | null
Access token expiration timestamp
refreshTokenExpiresAt
string (ISO 8601) | null
Refresh token expiration timestamp
scope
string | null
OAuth scopes granted
createdAt
string (ISO 8601)
Account connection timestamp
updatedAt
string (ISO 8601)
Last update timestamp
[
  {
    "id": "acc_1234567890",
    "accountId": "google_user_id_xyz",
    "providerId": "google",
    "userId": "user123",
    "accessToken": "ya29.a0AfH6SMB...",
    "refreshToken": "1//0gLn8...",
    "idToken": null,
    "accessTokenExpiresAt": "2024-01-20T16:30:00.000Z",
    "refreshTokenExpiresAt": null,
    "scope": "https://www.googleapis.com/auth/userinfo.email",
    "createdAt": "2024-01-15T10:30:00.000Z",
    "updatedAt": "2024-01-20T15:30:00.000Z"
  },
  {
    "id": "acc_0987654321",
    "accountId": "github_user_id_abc",
    "providerId": "github",
    "userId": "user123",
    "accessToken": "gho_16C7e42F292...",
    "refreshToken": "ghr_1B4a2e77...",
    "idToken": null,
    "accessTokenExpiresAt": "2024-01-21T10:30:00.000Z",
    "refreshTokenExpiresAt": "2024-07-15T10:30:00.000Z",
    "scope": "repo,user",
    "createdAt": "2024-01-16T12:00:00.000Z",
    "updatedAt": "2024-01-20T15:30:00.000Z"
  }
]
The response includes sensitive tokens. Never expose these in client-side code or logs.

Update Account

Update a connected account’s refresh token.
curl -X PUT http://localhost:3000/api/accounts \
  -H "Content-Type: application/json" \
  -H "Cookie: session=your-session-token" \
  -d '{
    "provider": "google",
    "refreshToken": "1//0gLn8..."
  }'

Request Body

provider
string
required
OAuth provider: google, github, or notion
refreshToken
string
required
New refresh token for the account

Response

Returns the updated account object.
{
  "id": "acc_1234567890",
  "accountId": "google_user_id_xyz",
  "providerId": "google",
  "userId": "user123",
  "accessToken": "ya29.a0AfH6SMB...",
  "refreshToken": "1//0gLn8...",
  "idToken": null,
  "accessTokenExpiresAt": "2024-01-20T16:30:00.000Z",
  "refreshTokenExpiresAt": null,
  "scope": "https://www.googleapis.com/auth/userinfo.email",
  "createdAt": "2024-01-15T10:30:00.000Z",
  "updatedAt": "2024-01-20T16:00:00.000Z"
}

Delete Account

Disconnect an OAuth account.
curl -X DELETE "http://localhost:3000/api/accounts?provider=google" \
  -H "Cookie: session=your-session-token"

Query Parameters

provider
string
required
OAuth provider to disconnect: google, github, or notion

Response

Returns the deleted account object.
{
  "id": "acc_1234567890",
  "accountId": "google_user_id_xyz",
  "providerId": "google",
  "userId": "user123",
  "accessToken": "ya29.a0AfH6SMB...",
  "refreshToken": "1//0gLn8...",
  "idToken": null,
  "accessTokenExpiresAt": "2024-01-20T16:30:00.000Z",
  "refreshTokenExpiresAt": null,
  "scope": "https://www.googleapis.com/auth/userinfo.email",
  "createdAt": "2024-01-15T10:30:00.000Z",
  "updatedAt": "2024-01-20T15:30:00.000Z"
}
Deleting an account will disconnect the OAuth integration and may break widgets that depend on it.

OAuth Flow

Connecting a new account typically follows this flow:
  1. Initiate OAuth - User clicks “Connect [Provider]” in the UI
  2. Redirect to Provider - User is redirected to the OAuth provider’s authorization page
  3. Authorization - User grants permissions
  4. Callback - Provider redirects back to Forge with authorization code
  5. Token Exchange - BetterAuth exchanges the code for access/refresh tokens
  6. Account Created - Account record is created in the database
  7. Widget Access - Widgets can now use the account to access provider APIs
This flow is handled automatically by BetterAuth. The Accounts API is primarily used to:
  • View connected accounts
  • Update refresh tokens when needed
  • Disconnect accounts

Token Refresh

Access tokens expire periodically. When a widget needs to use an expired token:
  1. Detect token expiration (check accessTokenExpiresAt)
  2. Use the refresh token to obtain a new access token
  3. Update the account using PUT /api/accounts
Most OAuth libraries handle this automatically.

Build docs developers (and LLMs) love