API Overview
Comprehensive guide to the Turbocamp centralized API architecture
Overview
Turbocamp uses a centralized API architecture where all authentication and business logic is handled by a single API server. This approach provides several advantages:
- 🏗️ Single Source of Truth: All business logic in one place
- 📱 Multi-Platform Support: Works with web, mobile, desktop, and third-party clients
- 🔐 Unified Authentication: Consistent auth flow across all platforms
- 🛡️ Enhanced Security: Centralized rate limiting and security controls
- ⚡ Easy Scaling: Scale API independently from frontend applications
API Base URL
| Environment | URL |
|---|---|
| Development | http://localhost:3002 |
| Production | https://api.turbocamp.dev |
Authentication Endpoints
Email & Password Authentication
Sign Up
POST /api/auth/sign-up/email
Content-Type: application/json
{
"email": "user@example.com",
"password": "securepassword123",
"name": "John Doe"
}Response Success (201):
{
"user": {
"id": "user_123",
"email": "user@example.com",
"name": "John Doe",
"emailVerified": false,
"image": null,
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
},
"session": {
"id": "session_456",
"userId": "user_123",
"expiresAt": "2024-01-08T00:00:00.000Z",
"token": "session_token_here"
}
}Response Error (400):
{
"error": {
"code": "USER_ALREADY_EXISTS",
"message": "A user with this email already exists"
}
}Sign In
POST /api/auth/sign-in/email
Content-Type: application/json
{
"email": "user@example.com",
"password": "securepassword123"
}Response Success (200):
{
"user": {
"id": "user_123",
"email": "user@example.com",
"name": "John Doe",
"emailVerified": true,
"image": null,
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
},
"session": {
"id": "session_456",
"userId": "user_123",
"expiresAt": "2024-01-08T00:00:00.000Z",
"token": "session_token_here"
}
}Sign Out
POST /api/auth/sign-out
Cookie: better-auth.session_token=session_token_hereResponse Success (200):
{
"success": true
}Get Session
GET /api/auth/get-session
Cookie: better-auth.session_token=session_token_hereResponse Success (200):
{
"user": {
"id": "user_123",
"email": "user@example.com",
"name": "John Doe",
"emailVerified": true,
"image": null,
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
},
"session": {
"id": "session_456",
"userId": "user_123",
"expiresAt": "2024-01-08T00:00:00.000Z",
"token": "session_token_here"
}
}Password Reset
Request Password Reset
POST /api/auth/forget-password
Content-Type: application/json
{
"email": "user@example.com",
"redirectTo": "https://yourapp.com/reset-password"
}Reset Password
POST /api/auth/reset-password
Content-Type: application/json
{
"token": "reset_token_here",
"password": "newpassword123"
}Error Handling
Standard Error Response Format
All API errors follow a consistent format:
{
"error": {
"code": "ERROR_CODE",
"message": "Human-readable error message",
"details": {
"field": "Additional error details (optional)"
}
}
}Common Error Codes
| Code | Status | Description |
|---|---|---|
USER_ALREADY_EXISTS | 400 | Email already registered |
INVALID_CREDENTIALS | 401 | Invalid email or password |
USER_NOT_FOUND | 404 | User not found |
INVALID_TOKEN | 401 | Invalid or expired token |
RATE_LIMIT_EXCEEDED | 429 | Too many requests |
EMAIL_NOT_VERIFIED | 403 | Email verification required |
WEAK_PASSWORD | 400 | Password doesn't meet requirements |
Rate Limiting
The API implements rate limiting to prevent abuse:
- Default: 100 requests per 10 seconds per IP
- Auth endpoints: 10 requests per 10 seconds per IP
- Password reset: 5 requests per hour per IP
Rate limit headers are included in responses:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 1640995200Security
CORS Configuration
The API accepts requests from:
localhost:3000(Web app)localhost:3001(Dashboard)- Production domains
- Custom origins via
ADDITIONAL_TRUSTED_ORIGINS
CSRF Protection
CSRF protection is enabled by default. The API validates the Origin header on all requests.
Cookie Security
- HTTPOnly: Cookies are not accessible via JavaScript
- Secure: Cookies are only sent over HTTPS in production
- SameSite: Set to
Laxfor cross-site compatibility - Cross-Domain: Shared across
*.turbocamp.devsubdomains
Integration Examples
React Native / Expo
// auth.ts
import AsyncStorage from '@react-native-async-storage/async-storage';
const API_BASE_URL = 'https://api.turbocamp.dev';
interface AuthResponse {
user: User;
session: Session;
}
class AuthService {
private sessionToken: string | null = null;
async initialize() {
this.sessionToken = await AsyncStorage.getItem('session_token');
}
async signUp(email: string, password: string, name: string): Promise<AuthResponse> {
const response = await fetch(`${API_BASE_URL}/api/auth/sign-up/email`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, password, name }),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error.message);
}
const data = await response.json();
this.sessionToken = data.session.token;
await AsyncStorage.setItem('session_token', this.sessionToken);
return data;
}
async signIn(email: string, password: string): Promise<AuthResponse> {
const response = await fetch(`${API_BASE_URL}/api/auth/sign-in/email`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, password }),
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error.message);
}
const data = await response.json();
this.sessionToken = data.session.token;
await AsyncStorage.setItem('session_token', this.sessionToken);
return data;
}
async getSession(): Promise<AuthResponse | null> {
if (!this.sessionToken) return null;
const response = await fetch(`${API_BASE_URL}/api/auth/get-session`, {
headers: {
'Cookie': `better-auth.session_token=${this.sessionToken}`,
},
});
if (!response.ok) {
await this.signOut();
return null;
}
return await response.json();
}
async signOut(): Promise<void> {
if (this.sessionToken) {
await fetch(`${API_BASE_URL}/api/auth/sign-out`, {
method: 'POST',
headers: {
'Cookie': `better-auth.session_token=${this.sessionToken}`,
},
});
}
this.sessionToken = null;
await AsyncStorage.removeItem('session_token');
}
}
export const authService = new AuthService();// App.tsx
import { authService } from './auth';
export default function App() {
useEffect(() => {
authService.initialize();
}, []);
const handleSignUp = async () => {
try {
const result = await authService.signUp(
'user@example.com',
'password123',
'John Doe'
);
console.log('Signed up:', result.user);
} catch (error) {
console.error('Sign up failed:', error.message);
}
};
const handleSignIn = async () => {
try {
const result = await authService.signIn(
'user@example.com',
'password123'
);
console.log('Signed in:', result.user);
} catch (error) {
console.error('Sign in failed:', error.message);
}
};
// ... rest of component
}Flutter / Dart
// auth_service.dart
import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
class AuthService {
static const String _baseUrl = 'https://api.turbocamp.dev';
static const String _sessionKey = 'session_token';
String? _sessionToken;
Future<void> initialize() async {
final prefs = await SharedPreferences.getInstance();
_sessionToken = prefs.getString(_sessionKey);
}
Future<Map<String, dynamic>> signUp({
required String email,
required String password,
required String name,
}) async {
final response = await http.post(
Uri.parse('$_baseUrl/api/auth/sign-up/email'),
headers: {'Content-Type': 'application/json'},
body: jsonEncode({
'email': email,
'password': password,
'name': name,
}),
);
if (response.statusCode != 201) {
final error = jsonDecode(response.body);
throw Exception(error['error']['message']);
}
final data = jsonDecode(response.body);
_sessionToken = data['session']['token'];
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_sessionKey, _sessionToken!);
return data;
}
Future<Map<String, dynamic>?> getSession() async {
if (_sessionToken == null) return null;
final response = await http.get(
Uri.parse('$_baseUrl/api/auth/get-session'),
headers: {
'Cookie': 'better-auth.session_token=$_sessionToken',
},
);
if (response.statusCode != 200) {
await signOut();
return null;
}
return jsonDecode(response.body);
}
Future<void> signOut() async {
if (_sessionToken != null) {
await http.post(
Uri.parse('$_baseUrl/api/auth/sign-out'),
headers: {
'Cookie': 'better-auth.session_token=$_sessionToken',
},
);
}
_sessionToken = null;
final prefs = await SharedPreferences.getInstance();
await prefs.remove(_sessionKey);
}
}cURL Examples
Sign Up
curl -X POST https://api.turbocamp.dev/api/auth/sign-up/email \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "securepassword123",
"name": "John Doe"
}'Sign In
curl -X POST https://api.turbocamp.dev/api/auth/sign-in/email \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "securepassword123"
}'Get Session
curl -X GET https://api.turbocamp.dev/api/auth/get-session \
-H "Cookie: better-auth.session_token=your_session_token_here"Environment Variables
When integrating with your client applications, make sure to set these environment variables:
# Your client app
NEXT_PUBLIC_API_URL=https://api.turbocamp.dev
# or for development
NEXT_PUBLIC_API_URL=http://localhost:3002
# For Better Auth client
NEXT_PUBLIC_BETTER_AUTH_URL=https://api.turbocamp.dev
# or for development
NEXT_PUBLIC_BETTER_AUTH_URL=http://localhost:3002Best Practices
Session Management
- Store session tokens securely (AsyncStorage, SharedPreferences, etc.)
- Always check session validity before making authenticated requests
- Implement automatic token refresh when possible
Error Handling
- Always handle network errors gracefully
- Show user-friendly error messages
- Implement retry logic for transient failures
Security
- Never store passwords in client applications
- Use HTTPS in production
- Validate all user inputs
- Implement proper session timeout
Performance
- Cache session data when appropriate
- Implement request deduplication
- Use efficient data structures
Testing
Development Environment
# Start the API server
cd apps/api
pnpm dev
# Test endpoints
curl -X GET http://localhost:3002/health
# Should return: OKProduction Environment
# Test health endpoint
curl -X GET https://api.turbocamp.dev/health
# Should return: OK✨ Happy Building! This centralized API approach gives you the flexibility to build amazing applications across all platforms while maintaining consistency and security.
Support
For integration support:
- 📚 Check the Better Auth Documentation
- 🐛 Report issues on GitHub
- 💬 Join our Discord Community