Open Connector

Connected Accounts

Create, list, refresh, and revoke user connections to third-party services.

A connected account is a user's linked OAuth token (or API key) for a specific auth config. It represents the result of a successful authorization flow: the user has granted your OAuth app access to their third-party account, and Open Connector has stored the resulting credentials encrypted in the vault.

Each connected account is scoped to a project and tied to a user identifier you supply. Agents reference connected accounts by ID when calling tools — the agent never sees the underlying token.

OAuth flow sequence

Initiate the connection

Your agent or backend calls POST /composio/api/v3.1/connected_accounts with an auth_config id (your registered OAuth app credentials) and a connection.user_id (your app's identifier for this user). Open Connector returns a redirect_url.

Redirect the user

Send the user to the redirect_url. They are taken to Open Connector's hosted connect page, then on to the third-party provider's authorization page (e.g., GitHub's OAuth consent screen) where they grant access.

Callback is handled by Open Connector

The provider redirects back to Open Connector's callback endpoint. Open Connector exchanges the authorization code for access and refresh tokens, encrypts them with AES-256-GCM, and stores them in the vault. The connection status transitions to ACTIVE.

Use the connection

The connected account is now ready. Pass its ID to tool execution calls — Open Connector decrypts the token server-side and injects it into the outbound request.

API operations

Create (initiate OAuth)

import { createClient } from "@open-connector/sdk";

const oc = createClient({
  apiKey: process.env.OPEN_CONNECTOR_API_KEY!,
  baseUrl: "https://api.openconnector.dev",
});

const connection = await oc.initiate({
  slug: "github",
  authConfigId: "ac_01j9abc123",
  entityId: "user_from_your_app",
});

console.log(connection.redirectUrl);
import Composio from "@composio/client";

const composio = new Composio({
  apiKey: process.env.OPEN_CONNECTOR_API_KEY!,
  baseURL: "https://api.openconnector.dev/composio",
});

const connection = await composio.connectedAccounts.create({
  auth_config: { id: "ac_01j9abc123" },
  connection: {
    user_id: "user_from_your_app",
    // callback_url is optional — omit to use Open Connector's hosted page
    callback_url: "https://yourapp.com/oauth/callback",
  },
} as any);

// Redirect user to this URL
console.log(connection.redirect_url);
curl -X POST "https://api.openconnector.dev/composio/api/v3.1/connected_accounts" \
  -H "x-api-key: oc_abc123xyz..." \
  -H "Content-Type: application/json" \
  -d '{
    "auth_config": { "id": "ac_01j9abc123" },
    "connection": {
      "user_id": "user_from_your_app",
      "callback_url": "https://yourapp.com/oauth/callback"
    }
  }'

Response (201):

{
  "id": "conn_01j9xyz789",
  "connectionData": { "authScheme": "OAUTH2", "val": { "status": "INITIATED" } },
  "status": "INITIATED",
  "redirect_url": "https://api.openconnector.dev/connect/<token>",
  "redirect_uri": "https://api.openconnector.dev/connect/<token>",
  "deprecated": { "uuid": "01j9xyz789", "authConfigUuid": "01j9abc123" }
}

Retrieve a connection

const account = await oc.getConnection({
  connectionId: "conn_01j9xyz789",
});

console.log(account.status);
console.log(account.providerSlug); // "github"
const account = await composio.connectedAccounts.get("conn_01j9xyz789");

console.log(account.status); // "ACTIVE" | "EXPIRED" | "INITIATED" | "REVOKED"
console.log(account.toolkit.slug); // "github"
curl "https://api.openconnector.dev/composio/api/v3.1/connected_accounts/conn_01j9xyz789" \
  -H "x-api-key: oc_abc123xyz..."

Response:

{
  "id": "conn_01j9xyz789",
  "status": "ACTIVE",
  "state": { "authScheme": "OAUTH2", "val": { "status": "ACTIVE" } },
  "toolkit": { "slug": "github" },
  "auth_config": { "id": "ac_01j9abc123", "auth_scheme": "OAUTH2" },
  "user_id": "user_from_your_app",
  "created_at": "2026-06-07T10:00:00.000Z",
  "updated_at": "2026-06-07T10:05:00.000Z"
}

List connections

const accounts = await oc.listConnections({});

for (const account of accounts.items) {
  console.log(account.id, account.status);
}
const accounts = await composio.connectedAccounts.list({
  toolkit_slugs: "github",  // optional filter
  user_ids: "user_123",     // optional filter
  limit: 20,
});

for (const account of accounts.items) {
  console.log(account.id, account.status);
}
curl "https://api.openconnector.dev/composio/api/v3.1/connected_accounts?toolkit_slugs=github&user_ids=user_123" \
  -H "x-api-key: oc_abc123xyz..."

Refresh a token

Force an immediate token refresh before it expires naturally. Useful if a token was revoked externally and you want to surface the error early.

await oc.refreshConnection({ connectionId: "conn_01j9xyz789" });
await composio.connectedAccounts.refresh("conn_01j9xyz789");
curl -X POST "https://api.openconnector.dev/composio/api/v3.1/connected_accounts/conn_01j9xyz789/refresh" \
  -H "x-api-key: oc_abc123xyz..."

Revoke and delete

Deleting a connected account revokes the stored token and removes it from the vault. The user will need to re-authorize to restore access.

await oc.revokeConnection({ connectionId: "conn_01j9xyz789" });
await oc.deleteConnection({ connectionId: "conn_01j9xyz789" });
await composio.connectedAccounts.delete("conn_01j9xyz789");
curl -X DELETE "https://api.openconnector.dev/composio/api/v3.1/connected_accounts/conn_01j9xyz789" \
  -H "x-api-key: oc_abc123xyz..."

Connected account status values

These are the wire status values returned by the Composio-compatible API. Internally Open Connector tracks native statuses (pending, active, error, expired, dropped, revoked, plus a disabled flag); the API maps them to the uppercase wire values below.

Prop

Type

Open Connector refreshes access tokens automatically before they expire during normal tool call execution. You do not need to poll for expiry or manually refresh unless you want to validate connectivity proactively.

For API_KEY connectors

For connectors with an API_KEY auth scheme (such as Telegram), there is no OAuth redirect. Instead, supply the credential inline under connection.state.val when creating the connection:

curl -X POST "https://api.openconnector.dev/composio/api/v3.1/connected_accounts" \
  -H "x-api-key: oc_abc123xyz..." \
  -H "Content-Type: application/json" \
  -d '{
    "auth_config": { "id": "ac_telegram_01" },
    "connection": {
      "user_id": "user_from_your_app",
      "state": {
        "val": {
          "apiKey": "123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
        }
      }
    }
  }'

The key is encrypted and stored in the vault. redirect_url comes back null; the connection is immediately ACTIVE.

On this page