Skip to content

Tenant/User Model

Every connection in Authpipe is scoped to a tenant (your customer’s organization). The attachment model on the provider config determines whether credentials are shared per-org or per-user.

One credential per tenant. The connection belongs to the organization, not a specific user.

Provider Config (attachment: "tenant")
└── Tenant "org_acme"
└── 1 connection (shared by all users)

Use when:

  • The credential represents the org’s integration (e.g., a shared Frame.io token)
  • Any authorized user can set up the connection for the whole team
  • You don’t need per-user credentials

Behavior:

  • getCredential looks up by tenant_id only
  • user_id is accepted but ignored for resolution
  • If a different user re-authorizes the same tenant, the existing connection is updated (upsert) — no duplicate is created
  • The user_id on the connection reflects who last authorized
// Any user in org_acme gets the same credential
const result = await authpipe.getCredential({
provider: "frame-io",
tenantId: "org_acme",
});

One credential per user within a tenant. Each user has their own connection.

Provider Config (attachment: "user")
└── Tenant "org_acme"
├── Connection for user_jane
├── Connection for user_bob
└── Connection for user_alice

Use when:

  • Each user needs their own token (e.g., personal Google Calendar)
  • Actions should be attributed to specific users
  • The provider’s API requires user-level authorization

Behavior:

  • getCredential looks up by tenant_id + user_id
  • user_id is required when creating auth sessions
// Each user has their own credential
const result = await authpipe.getCredential({
provider: "google-calendar",
tenantId: "org_acme",
userId: "user_jane",
});
QuestionTenantUser
Is the credential shared across the org?YesNo
Does each user need their own token?NoYes
Can any admin set it up for everyone?YesNo
Example providersFrame.io, Jira (project-level), Notion (workspace)Google Calendar, GitHub (personal), Slack (user token)

Set the attachment when creating the provider config:

await authpipe.createProviderConfig({
provider_id: "google-calendar",
attachment: "user",
// ...
});

Authpipe enforces uniqueness at the database level:

  • Tenant-attached: One active connection per (workspace, provider_config, installation, tenant_id)
  • User-attached: One active connection per (workspace, provider_config, installation, tenant_id, user_id)

Re-authorization upserts (updates tokens) rather than creating duplicates.

When a provider has both an installation and user connections, getCredential with credential_for: "any" (the default) tries the connection first, then falls back to the installation. See Installations for details.