Connect end-user accounts with ProjectConnector
Use ProjectConnector when every user of your product needs to connect their own provider account. Your backend identifies each user with externalUserId, creates authorization links, stores connected account IDs, and executes actions for that user.
This path uses a project API key shaped like oo_proj_…. It is separate from the personal api_… key used by Connector.
Prepare the project
Before writing the runtime flow, create these resources in OOMOL Console:
- A Connector project.
- A provider config for each service users can connect.
- A project API key stored in your backend secret manager.
The Connector for SaaS guide covers Console setup and the matching REST requests.
Install and initialize
npm install @oomol-lab/connector
import { ProjectConnector } from "@oomol-lab/connector";
const project = new ProjectConnector({
apiKey: process.env.OOMOL_PROJECT_API_KEY!,
});
Create an OAuth authorization request
Use a stable ID from your own user database as externalUserId:
const request = await project.connect.oauth("user_42", {
service: "gmail",
connectionName: "work",
returnUri: "https://app.example.com/connected",
});
redirectUserTo(request.authorizationUrl);
After the user authorizes, wait for the request to reach a final state:
const connected = await project.waitForConnection(request);
if (connected.status === "connected") {
saveConnectedAccountId(connected.connectedAccountId);
}
project.connect.oauth returns an authorization request that waits for the user. Only after authorization succeeds does waitForConnection return a connectedAccountId in the request result.
For API-key and custom-credential providers, use connect.apiKey or connect.customCredential. These methods validate the credential and return a connected account synchronously.
Execute for one user
const result = await project.execute(
"user_42",
"gmail.search_threads",
{ query: "is:unread" },
{ connectedAccountId: "ca-1" },
);
Pass connectedAccountId when you have it. It selects one specific account and avoids relying on the latest active account. connectionName is available when your product uses stable aliases instead.
Bind the user once with forUser when several operations belong to the same request or job:
const user = project.forUser("user_42");
await user.execute("slack.post_message", {
channel: "#general",
text: "shipped",
});
Keep product boundaries explicit
Your product authenticates its own users and controls which providers and actions they can use. Keep the project API key on the backend, pass a consistent externalUserId, and store the returned account selector beside the corresponding product user.
See the TypeScript SDK reference for authorization-request and connected-account lifecycle fields, precise action types, errors, retries, waiting options, and the complete ProjectConnector API.
Wanta