Design Philosophy
The OnlyFans SDK is built around developer experience , type safety , and reliability . Every design decision prioritizes making the OnlyFans API accessible, predictable, and safe to use.
Type Safety First Full TypeScript support with compile-time validation, IntelliSense, and structured error handling
Modular Architecture Organized by functionality - each module handles a specific aspect of the OnlyFans platform
Core Architecture
SDK Instance
The SDK is initialized as a single instance that provides access to all modules:
import OFSDK from "@ofauth/onlyfans-sdk"
// Single SDK instance with global configuration
const sdk = new OFSDK ({
mode: "access" , // ✅ Validated mode options
ofauthApiKey: "your-key" , // ✅ Required for managed access
debugLog: false // ✅ Optional debugging
})
// Access modules through the instance
sdk . messages // 💬 Messaging operations
sdk . posts // 📝 Content management
sdk . user // 👤 User operations
sdk . vault // 🗃️ Media management
// ... all other modules
Module Structure
Each module is self-contained and focused on a specific domain:
// Each module has consistent method signatures
interface ModulePattern {
// All methods follow the same pattern
async operation ({
authentication : AuthOptions , // ✅ Required auth context
... specificParams // ✅ Operation-specific parameters
}) : Promise < ApiResponse < T >> // ✅ Typed response
}
// Example: Messages module
const result = await sdk . messages . getChatsList ({
authentication: { connectionId: "conn_123" },
params: { limit: 20 , offset: 0 }
})
Type Safety System
Automatic Parameter Validation
The SDK validates all parameters at compile time and runtime:
// ✅ TypeScript catches invalid parameters before runtime
const result = await sdk . statistics . getStats ({
authentication: { connectionId: "conn_123" },
statType: "posts" , // ✅ Validates against allowed enum values
params: {
by: "purchases" , // ✅ Context-aware validation (valid for "posts")
startDate: new Date ( "2024-01-01" ), // ✅ Date object validation
limit: 20 // ✅ Number type enforcement
}
})
// ❌ TypeScript prevents invalid combinations at compile time
const invalid = await sdk . statistics . getStats ({
statType: "posts" ,
params: {
by: "revenue" // ❌ Not valid for "posts" statType
}
})
Response Type Safety
All API responses are fully typed with IntelliSense support:
const result = await sdk . messages . getChatsList ({
authentication: { connectionId }
})
if ( result . data ) {
// ✅ TypeScript knows the exact structure
result . data . list . forEach ( chat => {
console . log ( chat . user . username ) // ✅ IntelliSense available
console . log ( chat . lastMessage . text ) // ✅ Nested properties typed
console . log ( chat . unreadCount ) // ✅ Number types enforced
})
}
Authentication Architecture
Flexible Authentication Options
The SDK supports multiple authentication modes with automatic validation:
// Connection-based authentication (recommended)
const connectionAuth = {
authentication: { connectionId: "conn_123" }
}
// Session-based authentication (for direct access)
const sessionAuth = {
authentication: {
session: {
"user-id" : "123456789" ,
"user-agent" : "..." ,
"cookie" : "..."
}
}
}
// The SDK automatically validates which auth method is required
// ✅ Some operations require sessions, others accept connections
await sdk . subscriptions . subscribeToUser ({
authentication: { session: userData }, // ✅ Session required for user actions
userId: 123456789
})
Mode-Based Operation
The SDK adapts its behavior based on the configured mode:
Access Mode (Recommended)
// Uses OFAuth's managed service
const sdk = new OFSDK ({
mode: "access" ,
ofauthApiKey: "your-api-key"
})
// ✅ Simplified authentication
// ✅ Automatic request signing
// ✅ Rate limiting handled
// ✅ No manual session management
// Direct OnlyFans API access
const sdk = new OFSDK ({
mode: "direct" ,
ofauthApiKey: "your-api-key" // For dynamic rules
})
// ✅ Full control over requests
// ✅ Custom session management
// ⚠️ Manual rate limiting required
// ⚠️ Complex request signing
// Custom proxy/middleware
const sdk = new OFSDK ({
mode: "custom" ,
customOptions: {
baseUrl: "https://your-proxy.com" ,
signRequests: true ,
beforeRequest : ( url , request ) => {
// Custom request modification
return request
}
}
})
Error Handling Architecture
Structured Error Types
All errors follow a consistent structure with type safety:
interface ErrorResponse < T = any > {
error : {
statusCode : number // ✅ HTTP status
type : ErrorType // ✅ Categorized error types
message : string // ✅ Human-readable message
retry : boolean // ✅ Whether operation can be retried
details ?: T // ✅ Context-specific error data
}
}
// Usage with type safety
const result = await sdk . user . getUserInfo ( params )
if ( result . error ) {
switch ( result . error . type ) {
case "unauthorized" :
// Handle session expiry
break
case "forbidden" :
// Handle permission issues
break
case "bad_request" :
// result.error.details is typed based on the operation
console . log ( "Validation errors:" , result . error . details )
break
}
}
Module Organization
The SDK is organized into 10 focused modules :
Communication Messages - Chat, mass messaging, queued messages
Media Vault - File management, media organization, downloads
Content Posts - Content creation, management, scheduling
Users User - Profile data, user interactions, search
Authentication Link - Connection management, authentication flows
Account Account - Webhooks, account settings
Profile Self - Own profile management, settings, notifications
Subscriptions Subscriptions - Subscriber management, lists
Analytics Statistics - Performance metrics, earnings data
Upload Upload - File uploads, progress tracking
Request Flow Architecture
Unified Request Pipeline
All SDK operations follow the same request flow :
Automatic Request Enhancement
The SDK automatically enhances every request:
// What you write
const result = await sdk . posts . createPost ({
authentication: { connectionId: "conn_123" },
params: {
text: "Hello world!" ,
price: 5.00
}
})
// What the SDK does internally:
// 1. ✅ Validates all parameters (TypeScript + runtime)
// 2. ✅ Adds required headers (user-agent, content-type, etc.)
// 3. ✅ Signs request with dynamic rules (if needed)
// 4. ✅ Handles authentication context
// 5. ✅ Manages rate limiting
// 6. ✅ Processes response and provides typed data
// 7. ✅ Converts errors to structured format
Development Experience
IntelliSense and Autocomplete
The SDK provides comprehensive IDE support :
// ✅ Autocomplete shows all available modules
sdk . // → messages, posts, user, vault, etc.
// ✅ Method signatures with parameter descriptions
sdk . messages . createQueuedMessage ({
authentication: { connectionId: "..." },
params: {
// ✅ IntelliSense shows all valid parameters
text: "..." , // String - Message content
price: 5.00 , // Number - Message price
lockedText: "..." , // String - Preview text
// ... more parameters with descriptions
}
})
Runtime Validation
Beyond TypeScript, the SDK provides runtime safety :
// Even with TypeScript disabled, the SDK validates:
// ✅ Required parameters are present
// ✅ Parameter types are correct
// ✅ Enum values are valid
// ✅ Authentication context is appropriate
// ✅ Date formats are valid
// ✅ Array elements are correctly typed
const result = await sdk . statistics . getStats ({
// Runtime validation ensures this is safe
statType: userInput , // Validated against allowed values
params: {
startDate: new Date ( userDateInput ) // Date validation
}
})
Optimized for Scale
The SDK is designed for high-performance applications :
// ✅ Efficient batch operations
const [ messages , posts , stats ] = await Promise . all ([
sdk . messages . getChatsList ({ authentication: { connectionId } }),
sdk . posts . getMyPosts ({ authentication: { connectionId } }),
sdk . statistics . getStats ({
authentication: { connectionId },
statType: "posts"
})
])
// ✅ Built-in pagination support
async function getAllChats ( connectionId : string ) {
let allChats = []
let offset = 0
const limit = 50 // SDK validates pagination parameters
while ( true ) {
const result = await sdk . messages . getChatsList ({
authentication: { connectionId },
params: { limit , offset }
})
if ( ! result . data ?. list . length ) break
allChats . push ( ... result . data . list )
offset += limit
}
return allChats
}
Best Practices
Module Focus Use the Right Module
Each module has a specific purpose
Don’t mix concerns between modules
Leverage module-specific optimizations
Follow TypeScript guidance for parameter validation
Error Recovery Handle Errors Gracefully
Check result.error before using result.data
Use error types for appropriate responses
Implement retry logic for retriable errors
Log errors with sufficient context
Next Steps : Now that you understand the architecture, explore individual modules in the API Reference section to see how these principles apply to specific operations.