CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-supermemory

The official TypeScript library for the Supermemory API providing memory management, search, settings, and connection capabilities.

Pending
Overview
Eval results
Files

connections.mddocs/

Connection Management

Third-party service integrations for automated content synchronization and document importing from Notion, Google Drive, and OneDrive platforms.

Capabilities

Create Connection

Initializes a new connection to a third-party service and returns an authorization URL for OAuth flow completion.

/**
 * Initialize connection and get authorization URL
 * @param provider - Third-party service provider
 * @param params - Connection configuration parameters
 * @param options - Optional request configuration
 * @returns Promise resolving to connection creation response with auth URL
 */
create(
  provider: ConnectionProvider,
  params?: ConnectionCreateParams,
  options?: RequestOptions
): APIPromise<ConnectionCreateResponse>;

type ConnectionProvider = "notion" | "google-drive" | "onedrive";

interface ConnectionCreateParams {
  /** Container tags for organizing imported content */
  containerTags?: string[];
  /** Maximum number of documents to import (optional limit) */
  documentLimit?: number;
  /** Additional metadata for the connection */
  metadata?: { [key: string]: string | number | boolean } | null;
  /** OAuth redirect URL after authorization */
  redirectUrl?: string;
}

interface ConnectionCreateResponse {
  /** Unique connection identifier */
  id: string;
  /** OAuth authorization URL for user to visit */
  authLink: string;
  /** Time until authorization expires */
  expiresIn: string;
  /** Final redirect destination after OAuth completion */
  redirectsTo?: string;
}

Usage Examples:

import Supermemory from "supermemory";

const client = new Supermemory({ apiKey: "your-api-key" });

// Create Notion connection
const notionConnection = await client.connections.create("notion", {
  containerTags: ["team-workspace", "documentation"],
  documentLimit: 1000,
  redirectUrl: "https://your-app.com/oauth/callback",
  metadata: { team: "engineering", purpose: "documentation" },
});

console.log("Visit this URL to authorize:", notionConnection.authLink);
console.log("Connection ID:", notionConnection.id);

// Create Google Drive connection
const driveConnection = await client.connections.create("google-drive", {
  containerTags: ["personal", "documents"],
  documentLimit: 500,
});

// Create OneDrive connection with minimal configuration
const onedriveConnection = await client.connections.create("onedrive");

List Connections

Retrieves all connections for the organization with optional container tag filtering.

/**
 * List all connections
 * @param params - Optional filtering parameters
 * @param options - Optional request configuration
 * @returns Promise resolving to array of connections
 */
list(
  params?: ConnectionListParams,
  options?: RequestOptions
): APIPromise<ConnectionListResponse>;

interface ConnectionListParams {
  /** Filter connections by container tags */
  containerTags?: string[];
}

type ConnectionListResponse = ConnectionListItem[];

interface ConnectionListItem {
  /** Connection identifier */
  id: string;
  /** Connection creation timestamp */
  createdAt: string;
  /** Service provider name */
  provider: string;
  /** Document import limit */
  documentLimit?: number;
  /** Connected account email */
  email?: string;
  /** OAuth token expiration time */
  expiresAt?: string;
  /** Connection metadata */
  metadata?: { [key: string]: unknown };
}

Usage Examples:

// List all connections
const allConnections = await client.connections.list();
console.log(`Found ${allConnections.length} connections`);

// List connections filtered by tags
const teamConnections = await client.connections.list({
  containerTags: ["team-workspace"],
});

// Process connections
allConnections.forEach((connection) => {
  console.log(`${connection.provider} connection: ${connection.email}`);
  if (connection.expiresAt) {
    const expiry = new Date(connection.expiresAt);
    console.log(`Expires: ${expiry.toLocaleDateString()}`);
  }
});

Get Connection by ID

Retrieves detailed information about a specific connection using its unique identifier.

/**
 * Get connection details with id
 * @param connectionID - Unique connection identifier
 * @param options - Optional request configuration
 * @returns Promise resolving to connection details
 */
getByID(
  connectionID: string,
  options?: RequestOptions
): APIPromise<ConnectionGetByIDResponse>;

interface ConnectionGetByIDResponse {
  id: string;
  createdAt: string;
  provider: string;
  documentLimit?: number;
  email?: string;
  expiresAt?: string;
  metadata?: { [key: string]: unknown };
}

Usage Example:

const connection = await client.connections.getByID("connection-id-123");
console.log(`Connection: ${connection.provider} (${connection.email})`);
console.log(`Created: ${connection.createdAt}`);
console.log(`Document limit: ${connection.documentLimit || "unlimited"}`);

Get Connection by Tags

Finds a connection for a specific provider filtered by container tags.

/**
 * Get connection details with provider and container tags
 * @param provider - Service provider to search for
 * @param params - Container tags for filtering
 * @param options - Optional request configuration
 * @returns Promise resolving to matching connection
 */
getByTags(
  provider: ConnectionProvider,
  params: ConnectionGetByTagsParams,
  options?: RequestOptions
): APIPromise<ConnectionGetByTagsResponse>;

interface ConnectionGetByTagsParams {
  /** Container tags to match (required) */
  containerTags: string[];
}

interface ConnectionGetByTagsResponse {
  id: string;
  createdAt: string;
  provider: string;
  documentLimit?: number;
  email?: string;
  expiresAt?: string;
  metadata?: { [key: string]: unknown };
}

Usage Examples:

// Find Notion connection for specific workspace
const workspaceNotion = await client.connections.getByTags("notion", {
  containerTags: ["team-workspace", "engineering"],
});

// Find Google Drive connection for user
const userDrive = await client.connections.getByTags("google-drive", {
  containerTags: ["user_123", "personal"],
});

Delete Connection by ID

Permanently removes a connection using its unique identifier.

/**
 * Delete a specific connection by ID
 * @param connectionID - Connection identifier to delete
 * @param options - Optional request configuration
 * @returns Promise resolving to deletion confirmation
 */
deleteByID(
  connectionID: string,
  options?: RequestOptions
): APIPromise<ConnectionDeleteByIDResponse>;

interface ConnectionDeleteByIDResponse {
  /** Deleted connection ID */
  id: string;
  /** Service provider of deleted connection */
  provider: string;
}

Delete Connection by Provider

Removes connections for a specific provider filtered by container tags.

/**
 * Delete connection for a specific provider and container tags
 * @param provider - Service provider
 * @param params - Container tags for targeting specific connections
 * @param options - Optional request configuration
 * @returns Promise resolving to deletion confirmation
 */
deleteByProvider(
  provider: ConnectionProvider,
  params: ConnectionDeleteByProviderParams,
  options?: RequestOptions
): APIPromise<ConnectionDeleteByProviderResponse>;

interface ConnectionDeleteByProviderParams {
  /** Container tags to identify connections to delete (required) */
  containerTags: string[];
}

interface ConnectionDeleteByProviderResponse {
  /** Deleted connection ID */
  id: string;
  /** Service provider of deleted connection */
  provider: string;
}

Usage Examples:

// Delete specific connection
const deletedConnection = await client.connections.deleteByID("connection-id-123");
console.log(`Deleted ${deletedConnection.provider} connection: ${deletedConnection.id}`);

// Delete all Notion connections for a workspace
const deletedNotion = await client.connections.deleteByProvider("notion", {
  containerTags: ["old-workspace", "deprecated"],
});

Import/Sync Connection

Initiates manual synchronization of content from a connected service.

/**
 * Initiate a manual sync of connections
 * @param provider - Service provider to sync
 * @param params - Optional filtering for which connections to sync
 * @param options - Optional request configuration
 * @returns Promise resolving to sync status message
 */
import(
  provider: ConnectionProvider,
  params?: ConnectionImportParams,
  options?: RequestOptions
): APIPromise<string>;

interface ConnectionImportParams {
  /** Filter connections to sync by container tags */
  containerTags?: string[];
}

Usage Examples:

// Sync all Notion connections
const notionSync = await client.connections.import("notion");
console.log("Notion sync result:", notionSync);

// Sync specific Google Drive connections
const driveSync = await client.connections.import("google-drive", {
  containerTags: ["active-projects"],
});

// Sync all OneDrive connections
const onedriveSync = await client.connections.import("onedrive");

List Connection Documents

Retrieves documents that have been indexed from a specific provider's connections.

/**
 * List documents indexed for a provider and container tags
 * @param provider - Service provider
 * @param params - Optional filtering parameters
 * @param options - Optional request configuration
 * @returns Promise resolving to indexed documents list
 */
listDocuments(
  provider: ConnectionProvider,
  params?: ConnectionListDocumentsParams,
  options?: RequestOptions
): APIPromise<ConnectionListDocumentsResponse>;

interface ConnectionListDocumentsParams {
  /** Filter documents by container tags */
  containerTags?: string[];
}

type ConnectionListDocumentsResponse = ConnectionDocument[];

interface ConnectionDocument {
  /** Document identifier */
  id: string;
  /** Document creation timestamp */
  createdAt: string;
  /** Processing status */
  status: string;
  /** Document summary */
  summary: string | null;
  /** Document title */
  title: string | null;
  /** Document type */
  type: string;
  /** Last update timestamp */
  updatedAt: string;
}

Usage Examples:

// List all Google Drive documents
const driveDocuments = await client.connections.listDocuments("google-drive");
console.log(`Found ${driveDocuments.length} Google Drive documents`);

// List Notion documents for specific workspace
const workspaceDocuments = await client.connections.listDocuments("notion", {
  containerTags: ["team-workspace"],
});

// Process documents
driveDocuments.forEach((doc) => {
  console.log(`${doc.type}: ${doc.title} (${doc.status})`);
  if (doc.summary) {
    console.log(`Summary: ${doc.summary.substring(0, 100)}...`);
  }
});

Connection Workflows

Complete Connection Setup

const setupNotionConnection = async () => {
  try {
    // Step 1: Ensure custom OAuth keys are configured in settings
    await client.settings.update({
      notionCustomKeyEnabled: true,
      notionClientId: process.env.NOTION_CLIENT_ID,
      notionClientSecret: process.env.NOTION_CLIENT_SECRET,
    });
    
    // Step 2: Create connection
    const connection = await client.connections.create("notion", {
      containerTags: ["team-docs", "engineering"],
      documentLimit: 1000,
      redirectUrl: "https://your-app.com/oauth/notion/callback",
      metadata: {
        team: "engineering",
        purpose: "team-documentation",
        setupBy: "admin",
      },
    });
    
    console.log("Authorization URL:", connection.authLink);
    console.log("Connection ID:", connection.id);
    
    // Step 3: User completes OAuth flow (external process)
    // Your application handles the OAuth callback
    
    // Step 4: Verify connection was established
    const verifiedConnection = await client.connections.getByID(connection.id);
    console.log("Connection verified:", verifiedConnection.email);
    
    // Step 5: Initial sync
    const syncResult = await client.connections.import("notion", {
      containerTags: ["team-docs"],
    });
    console.log("Initial sync:", syncResult);
    
    return connection;
    
  } catch (error) {
    console.error("Connection setup failed:", error.message);
    throw error;
  }
};

Batch Connection Management

const manageMultipleConnections = async () => {
  // Get all connections
  const connections = await client.connections.list();
  
  // Group by provider
  const byProvider = connections.reduce((acc, conn) => {
    acc[conn.provider] = acc[conn.provider] || [];
    acc[conn.provider].push(conn);
    return acc;
  }, {} as Record<string, typeof connections>);
  
  // Check for expiring connections
  const expiringConnections = connections.filter((conn) => {
    if (!conn.expiresAt) return false;
    const expiry = new Date(conn.expiresAt);
    const daysUntilExpiry = (expiry.getTime() - Date.now()) / (1000 * 60 * 60 * 24);
    return daysUntilExpiry < 30; // Expiring in 30 days
  });
  
  console.log("Connections by provider:", Object.keys(byProvider));
  console.log("Expiring connections:", expiringConnections.length);
  
  // Sync all connections
  for (const provider of Object.keys(byProvider)) {
    try {
      const syncResult = await client.connections.import(provider as ConnectionProvider);
      console.log(`${provider} sync:`, syncResult);
    } catch (error) {
      console.error(`${provider} sync failed:`, error.message);
    }
  }
};

Connection Monitoring

const monitorConnections = async () => {
  const connections = await client.connections.list();
  
  for (const connection of connections) {
    console.log(`\n${connection.provider.toUpperCase()} Connection: ${connection.id}`);
    console.log(`Email: ${connection.email || "N/A"}`);
    console.log(`Created: ${new Date(connection.createdAt).toLocaleDateString()}`);
    
    if (connection.expiresAt) {
      const expiry = new Date(connection.expiresAt);
      const daysLeft = Math.ceil((expiry.getTime() - Date.now()) / (1000 * 60 * 60 * 24));
      console.log(`Expires: ${expiry.toLocaleDateString()} (${daysLeft} days)`);
      
      if (daysLeft < 7) {
        console.log("⚠️  Connection expires soon!");
      }
    }
    
    // Check document count
    try {
      const documents = await client.connections.listDocuments(
        connection.provider as ConnectionProvider,
        { containerTags: connection.metadata?.containerTags as string[] }
      );
      console.log(`Documents: ${documents.length}`);
      
      // Check processing status
      const statusCounts = documents.reduce((acc, doc) => {
        acc[doc.status] = (acc[doc.status] || 0) + 1;
        return acc;
      }, {} as Record<string, number>);
      
      console.log("Status breakdown:", statusCounts);
      
    } catch (error) {
      console.log("Could not fetch documents:", error.message);
    }
  }
};

Error Handling and Recovery

const handleConnectionErrors = async (provider: ConnectionProvider) => {
  try {
    const syncResult = await client.connections.import(provider);
    return { success: true, result: syncResult };
    
  } catch (error) {
    if (error instanceof AuthenticationError) {
      console.error(`${provider} authentication failed - OAuth token may have expired`);
      
      // Find connections for this provider
      const connections = await client.connections.list();
      const providerConnections = connections.filter(c => c.provider === provider);
      
      for (const connection of providerConnections) {
        console.log(`Connection ${connection.id} may need re-authorization`);
        // In a real application, you might trigger a re-authorization flow
      }
      
    } else if (error instanceof RateLimitError) {
      console.error(`${provider} rate limit exceeded - will retry later`);
      
      // Implement exponential backoff retry
      const delay = 60000; // 1 minute
      console.log(`Retrying ${provider} sync in ${delay / 1000} seconds`);
      
      return new Promise((resolve) => {
        setTimeout(async () => {
          try {
            const retryResult = await client.connections.import(provider);
            resolve({ success: true, result: retryResult });
          } catch (retryError) {
            resolve({ success: false, error: retryError.message });
          }
        }, delay);
      });
      
    } else if (error instanceof BadRequestError) {
      console.error(`${provider} sync failed - invalid configuration:`, error.message);
      
    } else {
      console.error(`${provider} sync failed:`, error.message);
    }
    
    return { success: false, error: error.message };
  }
};

// Usage
const syncAllProvidersWithErrorHandling = async () => {
  const providers: ConnectionProvider[] = ["notion", "google-drive", "onedrive"];
  
  const results = await Promise.all(
    providers.map(provider => handleConnectionErrors(provider))
  );
  
  results.forEach((result, index) => {
    const provider = providers[index];
    if (result.success) {
      console.log(`✅ ${provider}: ${result.result}`);
    } else {
      console.log(`❌ ${provider}: ${result.error}`);
    }
  });
};

Install with Tessl CLI

npx tessl i tessl/npm-supermemory

docs

connections.md

index.md

memories.md

search.md

settings.md

tile.json