Skip to content

Integrations Module

SDK reference for accessing integration configurations and OAuth tokens

The integrations module provides access to integration configurations and OAuth credentials.

from bifrost import integrations

Get integration configuration with OAuth tokens.

async def get(
name: str,
scope: str | None = None,
) -> IntegrationData | None
ParameterTypeDescription
namestrIntegration name (e.g., “HaloPSA”, “Microsoft_Graph”)
scopestr | NoneOrganization scope (see below)

Scope parameter:

  • None (default): Use execution context’s organization
  • Org UUID string: Target specific organization
  • "global": Access platform-level integration defaults

Note: Targeting a specific org via UUID requires provider org context. Managed orgs can only access their own scope. Use context.set_scope() to override scope for all calls at once.

IntegrationData object or None if not found.

integration = await integrations.get("Microsoft_Graph")
if integration:
# Access OAuth tokens
token = integration.oauth.access_token
# Access config values
tenant_id = integration.config.get("tenant_id")
# Entity ID for multi-tenant
entity = integration.entity_id

List all organization mappings for an integration.

async def list_mappings(name: str) -> list[IntegrationMappingResponse] | None
mappings = await integrations.list_mappings("HaloPSA")
if mappings:
for mapping in mappings:
print(f"Org: {mapping.organization_id}, Entity: {mapping.entity_id}")

Get a specific organization mapping for an integration.

async def get_mapping(
name: str,
scope: str | None = None,
entity_id: str | None = None,
) -> IntegrationMappingResponse | None
ParameterTypeDescription
namestrIntegration name
scopestr | NoneOrganization scope (see below)
entity_idstrExternal entity ID to filter by

Scope parameter:

  • None (default): Use execution context’s organization
  • Org UUID string: Target specific organization
# Get by scope
mapping = await integrations.get_mapping("HaloPSA", scope="org-123")
# Get by entity_id
mapping = await integrations.get_mapping("HaloPSA", entity_id="tenant-456")
if mapping:
print(f"Entity: {mapping.entity_id}, Config: {mapping.config}")

Create or update an organization mapping for an integration.

async def upsert_mapping(
name: str,
scope: str, # Required
entity_id: str,
entity_name: str | None = None,
config: dict | None = None,
) -> IntegrationMappingResponse
ParameterTypeDescription
namestrIntegration name
scopestrOrganization ID (required)
entity_idstrExternal entity ID (tenant, company, etc.)
entity_namestrDisplay name for the entity
configdictOrganization-specific configuration overrides
mapping = await integrations.upsert_mapping(
"HaloPSA",
scope="org-123",
entity_id="tenant-456",
entity_name="Acme Corp",
config={"custom_field": "value"}
)

Delete an organization mapping for an integration.

async def delete_mapping(
name: str,
scope: str, # Required
) -> bool
ParameterTypeDescription
namestrIntegration name
scopestrOrganization ID (required)
deleted = await integrations.delete_mapping("HaloPSA", scope="org-123")
class IntegrationData(BaseModel):
integration_id: str
entity_id: str | None # External entity ID (tenant, company, etc.)
entity_name: str | None # Display name for entity
config: dict # Merged configuration (defaults + org overrides)
oauth: OAuthCredentials | None
class OAuthCredentials(BaseModel):
connection_name: str
client_id: str | None
client_secret: str | None # Decrypted
authorization_url: str | None
token_url: str | None
scopes: list[str]
access_token: str | None # Decrypted
refresh_token: str | None # Decrypted
expires_at: str | None # ISO format
async def refresh(self) -> OAuthCredentials

Programmatically refresh the OAuth token. Works for both client_credentials and authorization_code flows. Updates access_token and expires_at in-place and persists the new token to the database.

integration = await integrations.get("Pax8")
await integration.oauth.refresh()
# integration.oauth.access_token is now a fresh token

This is useful when a provider’s tokens expire before their stated expires_in duration, or when you need to guarantee a fresh token before a critical API call.

class IntegrationMappingResponse(BaseModel):
id: str
integration_id: str
organization_id: str
entity_id: str | None
entity_name: str | None
oauth_token_id: str | None
config: dict
created_at: datetime
updated_at: datetime
from bifrost import workflow, integrations
import httpx
@workflow
async def sync_users():
# Get integration with OAuth
msft = await integrations.get("Microsoft_Graph")
if not msft or not msft.oauth:
return {"error": "Integration not configured"}
# Use the access token
async with httpx.AsyncClient() as client:
response = await client.get(
"https://graph.microsoft.com/v1.0/users",
headers={"Authorization": f"Bearer {msft.oauth.access_token}"}
)
return response.json()

Integration config is merged from two levels:

  1. Integration defaults - Platform-wide defaults
  2. Organization overrides - Per-org customizations

The config dict in IntegrationData contains the merged result.

OAuth tokens are:

  • Encrypted at rest in the database
  • Automatically decrypted when retrieved via SDK
  • Refreshed automatically by the platform when expired

If a token is rejected before its stated expiry (common with some providers like Pax8), use oauth.refresh() to fetch a fresh token on demand:

integration = await integrations.get("Pax8")
response = await client.get(url, headers={"Authorization": f"Bearer {integration.oauth.access_token}"})
if response.status_code == 401:
await integration.oauth.refresh()
response = await client.get(url, headers={"Authorization": f"Bearer {integration.oauth.access_token}"})