Skip to main content

Overview

The Connections module (sdk.link.connections) provides methods to manage active OnlyFans connections established through OFAuth Link. These connections represent authenticated relationships between your application and OnlyFans accounts.
Link vs Access: OFAuth Link handles the OAuth-style authentication flow where users securely connect their accounts. Once connected, you use OFAuth Access with these connection IDs to make API calls to OnlyFans endpoints.
Connection Lifecycle: Connections are created when users complete the OFAuth Link authentication flow and can be managed through these SDK methods.

Get All Connections

getAll(options)

Retrieve a list of connections with optional filtering and pagination.
options
GetConnectionsOptions
Optional filtering and pagination parameters.
options.status
'active' | 'expired' | 'error'
Filter connections by their current status.
options.platformUserId
number
Filter connections for a specific OnlyFans user ID.
options.limit
number
default:"20"
Maximum number of connections to return (1-100).
options.offset
number
default:"0"
Number of connections to skip for pagination.
list
Connection[]
required
Array of connection objects.
total
number
required
Total number of connections matching the criteria.
hasMore
boolean
required
Whether there are more connections beyond the current page.
const { data: connections, error } = await sdk.link.connections.getAll({
  status: "active",
  limit: 50,
  offset: 0
})

if (error) {
  console.error("Failed to get connections:", error.message)
} else {
  console.log(`Found ${connections.total} total connections`)
  console.log(`Showing ${connections.list.length} connections`)
  
  connections.list.forEach(connection => {
    console.log(`Connection ${connection.id}:`)
    console.log(`  User: ${connection.metadata?.username}`)
    console.log(`  Status: ${connection.status}`)
    console.log(`  Created: ${connection.createdAt}`)
  })
  
  if (connections.hasMore) {
    console.log("More connections available")
  }
}
const { data: userConnections, error } = await sdk.link.connections.getAll({
  platformUserId: 123456789,
  status: "active"
})

if (data) {
  if (userConnections.list.length > 0) {
    console.log("User has active connections:")
    userConnections.list.forEach(conn => {
      console.log(`  ${conn.id} - ${conn.status}`)
    })
  } else {
    console.log("No active connections for this user")
  }
}
{
  "data": {
    "list": [
      {
        "id": "conn_123456789",
        "platformUserId": "123456789",
        "status": "active",
        "createdAt": "2024-01-15T10:30:00Z",
        "updatedAt": "2024-01-15T10:30:00Z",
        "expiresAt": "2024-02-15T10:30:00Z",
        "metadata": {
          "username": "example_user",
          "displayName": "Example User",
          "lastActivity": "2024-01-20T15:45:00Z"
        }
      }
    ],
    "total": 1,
    "hasMore": false
  },
  "error": undefined
}

Get Connection by ID

getById(connectionId)

Retrieve details for a specific connection.
connectionId
string
required
The unique connection identifier.
connection
Connection
required
The connection object with full details.
const { data: connection, error } = await sdk.link.connections.getById(
  "conn_123456789"
)

if (error) {
  if (error.type === "not_found") {
    console.log("Connection not found")
  } else {
    console.error("Error getting connection:", error.message)
  }
} else {
  console.log("Connection details:")
  console.log(`  ID: ${connection.id}`)
  console.log(`  Status: ${connection.status}`)
  console.log(`  User: ${connection.metadata?.username}`)
  console.log(`  Created: ${connection.createdAt}`)
  
  if (connection.status === "active") {
    // Use this connection for API calls
    const { data: profile } = await sdk.self.getMe({
      authentication: { connectionId: connection.id }
    })
    console.log("Profile:", profile?.username)
  }
}
{
  "data": {
    "id": "conn_123456789",
    "platformUserId": "123456789",
    "status": "active",
    "createdAt": "2024-01-15T10:30:00Z",
    "updatedAt": "2024-01-20T15:45:00Z",
    "expiresAt": "2024-02-15T10:30:00Z",
    "metadata": {
      "username": "example_user",
      "displayName": "Example User",
      "lastActivity": "2024-01-20T15:45:00Z"
    }
  },
  "error": undefined
}

Delete Connection

delete(connectionId)

Delete a specific connection, revoking access to the associated OnlyFans account.
connectionId
string
required
The unique connection identifier to delete.
success
boolean
required
Whether the deletion was successful.
message
string
required
Confirmation message about the deletion.
const { data: result, error } = await sdk.link.connections.delete(
  "conn_123456789"
)

if (error) {
  if (error.type === "not_found") {
    console.log("Connection was already deleted or doesn't exist")
  } else {
    console.error("Failed to delete connection:", error.message)
  }
} else {
  console.log("Connection deleted:", result.message)
  
  // Remove connection from your local storage/database
  await removeStoredConnection("conn_123456789")
}
{
  "data": {
    "success": true,
    "message": "Connection conn_123456789 has been successfully deleted"
  },
  "error": undefined
}
Permanent Action: Deleting a connection permanently revokes access to the OnlyFans account. The user would need to re-authenticate through the Link flow to restore access.

Connection Status Management

Understanding Connection Status

Connections can have different statuses that affect their usability:
Status: activeConnection is valid and can be used for API calls.
if (connection.status === "active") {
  // Safe to use for API calls
  const { data } = await sdk.self.getMe({
    authentication: { connectionId: connection.id }
  })
}

Monitoring Connection Health

async function checkConnectionHealth(connectionId: string): Promise<boolean> {
  const { data: connection, error } = await sdk.link.connections.getById(
    connectionId
  )
  
  if (error) {
    console.error("Failed to check connection:", error.message)
    return false
  }
  
  switch (connection.status) {
    case "active":
      // Additional verification with a simple API call
      const { error: apiError } = await sdk.self.getMe({
        authentication: { connectionId }
      })
      
      if (apiError && apiError.type === "unauthorized") {
        console.log("Connection appears active but API calls fail")
        return false
      }
      
      return true
      
    case "expired":
      console.log("Connection expired")
      return false
      
    case "error":
      console.log("Connection in error state")
      return false
      
    default:
      console.log("Unknown connection status:", connection.status)
      return false
  }
}

// Usage
const isHealthy = await checkConnectionHealth("conn_123456789")
if (!isHealthy) {
  // Handle unhealthy connection
  await handleConnectionIssue("conn_123456789")
}

Bulk Connection Management

Managing Multiple Connections

async function getActiveConnectionsForUsers(
  userIds: number[]
): Promise<Map<number, string>> {
  const activeConnections = new Map<number, string>()
  
  // Get all active connections
  const { data: connections, error } = await sdk.link.connections.getAll({
    status: "active",
    limit: 100
  })
  
  if (error) {
    console.error("Failed to get connections:", error.message)
    return activeConnections
  }
  
  // Map user IDs to connection IDs
  connections.list.forEach(connection => {
    const userId = parseInt(connection.platformUserId)
    if (userIds.includes(userId)) {
      activeConnections.set(userId, connection.id)
    }
  })
  
  return activeConnections
}

// Usage
const userIds = [123456, 789012, 345678]
const connectionMap = await getActiveConnectionsForUsers(userIds)

console.log(`Found connections for ${connectionMap.size} users`)
connectionMap.forEach((connectionId, userId) => {
  console.log(`User ${userId}: ${connectionId}`)
})

Cleanup Expired Connections

async function cleanupExpiredConnections(): Promise<number> {
  let deletedCount = 0
  let offset = 0
  const limit = 50
  
  while (true) {
    const { data: connections, error } = await sdk.link.connections.getAll({
      status: "expired",
      limit,
      offset
    })
    
    if (error) {
      console.error("Failed to get expired connections:", error.message)
      break
    }
    
    if (connections.list.length === 0) {
      break // No more expired connections
    }
    
    // Delete expired connections
    const deletePromises = connections.list.map(async connection => {
      const { error: deleteError } = await sdk.link.connections.delete(
        connection.id
      )
      
      if (!deleteError) {
        deletedCount++
        console.log(`Deleted expired connection: ${connection.id}`)
      } else {
        console.error(`Failed to delete ${connection.id}:`, deleteError.message)
      }
    })
    
    await Promise.all(deletePromises)
    
    if (!connections.hasMore) {
      break
    }
    
    offset += limit
  }
  
  return deletedCount
}

// Run cleanup
const deleted = await cleanupExpiredConnections()
console.log(`Cleaned up ${deleted} expired connections`)

Error Handling

Common error scenarios when working with connections:

Connection Not Found

const { data, error } = await sdk.link.connections.getById("conn_invalid")

if (error && error.type === "not_found") {
  console.log("Connection doesn't exist or was already deleted")
  // Remove from local storage if needed
  await removeLocalConnection("conn_invalid")
}

Permission Errors

const { data, error } = await sdk.link.connections.delete("conn_123456789")

if (error && error.type === "forbidden") {
  console.log("You don't have permission to delete this connection")
  // This connection might belong to another application
}

Rate Limiting

const { data, error } = await sdk.link.connections.getAll({ limit: 100 })

if (error && error.type === "too_many_requests") {
  console.log("Rate limited, waiting before retry...")
  await new Promise(resolve => setTimeout(resolve, 5000))
  // Retry the request
}

Integration Patterns

Connection-Based User Management

class UserConnectionManager {
  private connectionCache = new Map<string, any>()
  
  async getUserConnection(userId: string): Promise<string | null> {
    // Check cache first
    if (this.connectionCache.has(userId)) {
      const cached = this.connectionCache.get(userId)
      if (Date.now() - cached.timestamp < 300000) { // 5 min cache
        return cached.connectionId
      }
    }
    
    // Find active connection for user
    const { data: connections, error } = await sdk.link.connections.getAll({
      platformUserId: parseInt(userId),
      status: "active",
      limit: 1
    })
    
    if (error || connections.list.length === 0) {
      return null
    }
    
    const connectionId = connections.list[0].id
    
    // Cache the result
    this.connectionCache.set(userId, {
      connectionId,
      timestamp: Date.now()
    })
    
    return connectionId
  }
  
  async clearUserCache(userId: string): void {
    this.connectionCache.delete(userId)
  }
}

// Usage
const connectionManager = new UserConnectionManager()

const connectionId = await connectionManager.getUserConnection("123456")
if (connectionId) {
  const { data: profile } = await sdk.self.getMe({
    authentication: { connectionId }
  })
  console.log("User profile:", profile)
} else {
  console.log("No active connection for user")
}

Best Practices

Caching: Cache connection lookups to avoid repeated API calls, but implement proper cache invalidation.
Status Monitoring: Regularly check connection status, especially for long-running applications.
Graceful Degradation: Handle connection failures gracefully and provide clear feedback to users.

Next Steps