This document provides comprehensive documentation for all REST API endpoints in the NextJS starter template with Better Auth v1.4+ and Drizzle ORM v0.45+, including authentication, user management, organization management, and data operations.
- Base URL: https://yourdomain.com/api/v1
- Framework: Next.js 16 with App Router
- Database: PostgreSQL with Drizzle ORM
- Authentication: Better Auth v1.4+ (JWT + Session Cookies)
- Protocol: HTTPS
- Content-Type: application/json
interface APIResponse<T = any> {
traceId: string; // Unique request identifier
code: string; // Response code (00 = success, 01-99 = errors)
message: string; // Human-readable message
data?: T; // Response payload (if applicable)
hostId?: string; // Server identifier
responseAt?: string; // ISO timestamp of response
timeConsume?: number; // Response time in milliseconds
}interface ErrorCodes {
"00": "Success";
"01": "Validation Error";
"02": "Authentication Failed";
"03": "Authorization Failed";
"04": "Resource Not Found";
"05": "Server Error";
"06": "Database Error";
"07": "Rate Limited";
"08": "Method Not Allowed";
"09": "Invalid Input";
"10": "External Service Error";
}Authenticate user with email and password.
{
"email": "user@example.com",
"password": "securePassword123",
"rememberMe": false
}{
"traceId": "req_123456789",
"code": "00",
"message": "Login successful",
"data": {
"user": {
"id": "user_123",
"name": "John Doe",
"email": "user@example.com",
"role": "USER",
"emailVerified": true,
"createdAt": "2025-01-01T00:00:00.000Z"
},
"session": {
"token": "jwt_token_here",
"expiresAt": "2025-01-04T00:00:00.000Z"
},
"organizations": [
{
"id": "org_123",
"name": "Acme Corp",
"role": "OWNER"
}
]
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 150
}{
"traceId": "req_123456789",
"code": "02",
"message": "Invalid email or password",
"data": null,
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 100
}- 400 - Invalid input format
- 401 - Invalid credentials
- 403 - Account banned or not verified
- 429 - Too many login attempts
Register a new user account.
{
"name": "John Doe",
"email": "john@example.com",
"password": "securePassword123",
"confirmPassword": "securePassword123",
"organizationName": "Optional organization name",
"acceptTerms": true
}{
"traceId": "req_123456789",
"code": "00",
"message": "Registration successful. Please check your email to verify your account.",
"data": {
"user": {
"id": "user_123",
"name": "John Doe",
"email": "john@example.com",
"role": "USER",
"emailVerified": false,
"createdAt": "2025-01-01T00:00:00.000Z"
}
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 200
}- 400 - Validation error, weak password, terms not accepted
- 409 - Email already exists
- 422 - Invalid input data
Initiate password reset process.
{
"email": "user@example.com"
}{
"traceId": "req_123456789",
"code": "00",
"message": "If an account exists with this email, a password reset link has been sent.",
"data": null,
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 150
}Complete password reset with token.
{
"token": "reset_token_here",
"password": "newSecurePassword123",
"confirmPassword": "newSecurePassword123"
}{
"traceId": "req_123456789",
"code": "00",
"message": "Password reset successful. You can now login with your new password.",
"data": null,
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 100
}- 400 - Invalid token, password mismatch
- 404 - Token not found or expired
Terminate user session.
{
"allDevices": false
}{
"traceId": "req_123456789",
"code": "00",
"message": "Logout successful",
"data": null,
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 50
}Retrieve paginated list of users (Admin/Superadmin only).
interface UsersQuery {
page?: number; // Page number (default: 1)
limit?: number; // Items per page (default: 10, max: 100)
search?: string; // Search term (name, email)
role?: "USER" | "ADMIN" | "SUPERADMIN";
sortBy?: "name" | "email" | "createdAt" | "lastLogin";
sortOrder?: "asc" | "desc";
emailVerified?: boolean;
banned?: boolean;
}GET /api/v1/users?page=1&limit=10&search=john&role=USER&sortBy=createdAt&sortOrder=desc{
"traceId": "req_123456789",
"code": "00",
"message": "Users retrieved successfully",
"data": {
"users": [
{
"id": "user_123",
"name": "John Doe",
"email": "john@example.com",
"role": "USER",
"emailVerified": true,
"banned": false,
"createdAt": "2025-01-01T00:00:00.000Z",
"lastLoginAt": "2025-01-01T12:00:00.000Z",
"organizations": [
{
"id": "org_123",
"name": "Acme Corp",
"role": "OWNER"
}
]
}
],
"pagination": {
"page": 1,
"limit": 10,
"total": 25,
"totalPages": 3,
"hasNext": true,
"hasPrev": false
}
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 120
}- 401 - Authentication required
- 403 - Insufficient permissions
- 400 - Invalid query parameters
Retrieve specific user details.
GET /api/v1/users/user_123{
"traceId": "req_123456789",
"code": "00",
"message": "User retrieved successfully",
"data": {
"user": {
"id": "user_123",
"name": "John Doe",
"email": "john@example.com",
"role": "USER",
"emailVerified": true,
"banned": false,
"banReason": null,
"banExpires": null,
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-01T12:00:00.000Z",
"lastLoginAt": "2025-01-01T12:00:00.000Z",
"organizations": [
{
"id": "org_123",
"name": "Acme Corp",
"role": "OWNER",
"createdAt": "2025-01-01T00:00:00.000Z"
}
],
"sessions": [
{
"id": "session_123",
"createdAt": "2025-01-01T12:00:00.000Z",
"expiresAt": "2025-01-04T12:00:00.000Z",
"ipAddress": "192.168.1.1",
"userAgent": "Mozilla/5.0..."
}
]
}
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 80
}- 401 - Authentication required
- 403 - Cannot access other users (non-admin)
- 404 - User not found
Create a new user (Admin/Superadmin only).
{
"name": "Jane Smith",
"email": "jane@example.com",
"password": "securePassword123",
"role": "USER",
"organizationId": "org_123",
"organizationRole": "MEMBER",
"emailVerified": true
}{
"traceId": "req_123456789",
"code": "00",
"message": "User created successfully",
"data": {
"user": {
"id": "user_456",
"name": "Jane Smith",
"email": "jane@example.com",
"role": "USER",
"emailVerified": true,
"createdAt": "2025-01-01T12:00:00.000Z"
}
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 200
}Update user information.
PUT /api/v1/users/user_123{
"name": "John Updated",
"role": "ADMIN",
"emailVerified": true,
"banned": false
}{
"traceId": "req_123456789",
"code": "00",
"message": "User updated successfully",
"data": {
"user": {
"id": "user_123",
"name": "John Updated",
"email": "john@example.com",
"role": "ADMIN",
"emailVerified": true,
"updatedAt": "2025-01-01T12:00:00.000Z"
}
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 150
}- 400 - Invalid data, role assignment not allowed
- 401 - Authentication required
- 403 - Cannot modify higher role user
- 404 - User not found
Delete a user (Admin/Superadmin only).
DELETE /api/v1/users/user_123{
"traceId": "req_123456789",
"code": "00",
"message": "User deleted successfully",
"data": null,
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 100
}- 401 - Authentication required
- 403 - Cannot delete self or higher role user
- 404 - User not found
Get user by email address.
GET /api/v1/users/email/john@example.com{
"traceId": "req_123456789",
"code": "00",
"message": "User retrieved successfully",
"data": {
"user": {
"id": "user_123",
"name": "John Doe",
"email": "john@example.com",
"role": "USER",
"emailVerified": true,
"createdAt": "2025-01-01T00:00:00.000Z"
}
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 80
}Retrieve user's organizations (for authenticated user's context).
GET /api/v1/users/organizations{
"success": true,
"data": {
"organizations": [
{
"id": "org_123",
"name": "Acme Corp",
"slug": "acme-corp",
"logo": "https://example.com/logo.png",
"role": "owner",
"memberCount": 5,
"createdAt": "2025-01-01T00:00:00.000Z"
}
],
"currentOrganization": {
"id": "org_123",
"name": "Acme Corp",
"slug": "acme-corp",
"logo": "https://example.com/logo.png",
"role": "owner",
"memberCount": 5,
"createdAt": "2025-01-01T00:00:00.000Z"
}
}
}Retrieve all organizations (Superadmin/Admin only). Returns paginated list with search and sorting capabilities.
interface OrganizationsQuery {
page?: number; // Page number (default: 1)
limit?: number; // Items per page (default: 10, max: 100)
search?: string; // Search term (organization name)
sort?: string; // Sort by field (name, createdAt)
}GET /api/v1/organizations?page=1&limit=10&search=acme&sort=createdAt{
"traceId": "req_123456789",
"code": "00",
"message": "Success",
"data": [
{
"id": "org_123",
"name": "Acme Corp",
"slug": "acme-corp",
"logo": "https://example.com/logo.png",
"metadata": null,
"memberCount": 5,
"createdAt": "2025-01-01T00:00:00.000Z"
}
],
"paging": {
"size": 10,
"total_page": 3,
"current_page": 1,
"total": 25
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 120
}- 401 - Authentication required
- 403 - Only SUPERADMIN and ADMIN can access
- 400 - Invalid query parameters
Create new organization (Superadmin/Admin only).
{
"name": "New Company",
"slug": "new-company",
"logo": "https://example.com/logo.png",
"metadata": {
"industry": "Technology",
"size": "enterprise"
}
}{
"traceId": "req_123456789",
"code": "00",
"message": "Organization created successfully",
"data": {
"id": "org_456",
"name": "New Company",
"slug": "new-company",
"logo": "https://example.com/logo.png",
"metadata": {
"industry": "Technology",
"size": "enterprise"
},
"createdAt": "2025-01-01T12:00:00.000Z",
"role": "owner"
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 150
}- 401 - Authentication required
- 403 - Only SUPERADMIN and ADMIN can create organizations
- 400 - Validation error (name and slug required)
- 409 - Organization with this slug already exists
Get specific organization details (Superadmin/Admin only).
GET /api/v1/organizations/org_123{
"traceId": "req_123456789",
"code": "00",
"message": "Success",
"data": {
"id": "org_123",
"name": "Acme Corp",
"slug": "acme-corp",
"logo": "https://example.com/logo.png",
"metadata": {
"industry": "Technology",
"size": "enterprise"
},
"memberCount": 5,
"createdAt": "2025-01-01T00:00:00.000Z"
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 80
}- 401 - Authentication required
- 403 - Only SUPERADMIN and ADMIN can access
- 404 - Organization not found
Update organization information (Superadmin/Admin only).
{
"name": "Updated Company Name",
"slug": "updated-company-slug",
"logo": "https://example.com/new-logo.png",
"metadata": {
"industry": "Finance",
"size": "mid-size"
}
}{
"traceId": "req_123456789",
"code": "00",
"message": "Organization updated successfully",
"data": {
"id": "org_123",
"name": "Updated Company Name",
"slug": "updated-company-slug",
"logo": "https://example.com/new-logo.png",
"metadata": {
"industry": "Finance",
"size": "mid-size"
},
"memberCount": 5,
"createdAt": "2025-01-01T00:00:00.000Z"
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 150
}- 401 - Authentication required
- 403 - Only SUPERADMIN and ADMIN can update organizations
- 400 - Validation error
- 404 - Organization not found
- 409 - Organization with this slug already exists
Delete an organization (Superadmin/Admin only).
DELETE /api/v1/organizations/org_123{
"traceId": "req_123456789",
"code": "00",
"message": "Organization deleted successfully",
"data": null,
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 100
}- 401 - Authentication required
- 403 - Only SUPERADMIN and ADMIN can delete organizations
- 404 - Organization not found
Get all members of a specific organization.
GET /api/v1/organizations/org_123/members{
"traceId": "req_123456789",
"code": "00",
"message": "Success",
"data": [
{
"id": "member_123",
"userId": "user_123",
"organizationId": "org_123",
"role": "owner",
"user": {
"id": "user_123",
"name": "John Doe",
"email": "john@example.com",
"avatar": "https://example.com/avatar.jpg"
},
"createdAt": "2025-01-01T00:00:00.000Z"
}
],
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 100
}Invite user to join an organization.
{
"email": "invitee@example.com",
"role": "member",
"message": "Join our team at Acme Corp!"
}{
"traceId": "req_123456789",
"code": "00",
"message": "Invitation sent successfully",
"data": {
"id": "inv_123",
"email": "invitee@example.com",
"organizationId": "org_123",
"role": "member",
"message": "Join our team at Acme Corp!",
"status": "pending",
"expiresAt": "2025-01-08T12:00:00.000Z"
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 200
}Get all pending invitations for an organization.
GET /api/v1/organizations/org_123/invitations{
"traceId": "req_123456789",
"code": "00",
"message": "Success",
"data": [
{
"id": "inv_123",
"email": "invitee@example.com",
"organizationId": "org_123",
"role": "member",
"status": "pending",
"createdAt": "2025-01-01T00:00:00.000Z",
"expiresAt": "2025-01-08T12:00:00.000Z"
}
],
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 120
}Accept organization invitation.
POST /api/accept-invitation/inv_123{
"traceId": "req_123456789",
"code": "00",
"message": "Invitation accepted successfully",
"data": {
"membership": {
"id": "mem_123",
"organizationId": "org_123",
"userId": "user_456",
"role": "MEMBER",
"createdAt": "2025-01-01T12:00:00.000Z"
}
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 150
}Application health status.
GET /api/health{
"traceId": "req_123456789",
"code": "00",
"message": "Application is healthy",
"data": {
"status": "healthy",
"timestamp": "2025-01-01T12:00:00.000Z",
"version": "1.0.0",
"environment": "production",
"uptime": 86400,
"database": {
"status": "connected",
"responseTime": 5
},
"memory": {
"used": "256MB",
"total": "512MB"
}
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 10
}Upload file to server.
POST /api/v1/upload
Content-Type: multipart/form-data
file: [binary file data]
folder: "avatars"
maxSize: 5242880{
"traceId": "req_123456789",
"code": "00",
"message": "File uploaded successfully",
"data": {
"file": {
"id": "file_123",
"name": "avatar.jpg",
"url": "https://example.com/uploads/avatars/avatar_123.jpg",
"size": 1024000,
"type": "image/jpeg",
"folder": "avatars",
"uploadedAt": "2025-01-01T12:00:00.000Z"
}
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 500
}Export user data in various formats.
{
"format": "csv",
"filters": {
"role": "USER",
"emailVerified": true,
"dateRange": {
"from": "2025-01-01",
"to": "2025-01-31"
}
},
"fields": ["id", "name", "email", "role", "createdAt"]
}{
"traceId": "req_123456789",
"code": "00",
"message": "Export generated successfully",
"data": {
"downloadUrl": "https://example.com/exports/users_20250101.csv",
"filename": "users_20250101.csv",
"size": 1024000,
"expiresAt": "2025-01-02T12:00:00.000Z"
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 2000
}interface RateLimitConfig {
"/api/v1/auth/login": {
requests: 5;
window: "15m";
blockDuration: "15m";
};
"/api/v1/auth/register": {
requests: 3;
window: "1h";
blockDuration: "1h";
};
"/api/v1/auth/reset": {
requests: 3;
window: "1h";
blockDuration: "1h";
};
"/api/v1/users": {
requests: 100;
window: "1h";
blockDuration: "1h";
};
}{
"traceId": "req_123456789",
"code": "07",
"message": "Too many requests. Please try again later.",
"data": {
"retryAfter": 900,
"limit": 5,
"remaining": 0,
"reset": "2025-01-01T12:15:00.000Z"
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 10
}Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...Cookie: auth-token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...; auth-jwt=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...Content-Type: application/json
Accept: application/json
User-Agent: YourApp/1.0
X-Request-ID: optional-request-id{
"traceId": "req_123456789",
"code": "error_code",
"message": "Human-readable error message",
"data": {
"field": "Additional error details",
"validationErrors": [
{
"field": "email",
"message": "Invalid email format"
}
]
},
"responseAt": "2025-01-01T12:00:00.000Z",
"timeConsume": 50
}- 200 - Success
- 201 - Created successfully
- 400 - Bad request (validation error)
- 401 - Unauthorized (authentication required)
- 403 - Forbidden (insufficient permissions)
- 404 - Not found
- 409 - Conflict (resource already exists)
- 422 - Unprocessable entity
- 429 - Too many requests (rate limited)
- 500 - Internal server error
- 502 - Bad gateway (external service error)
- 503 - Service unavailable
- URL Path Versioning: /api/v1/, /api/v2/
- Backward Compatibility: Maintain v1 while introducing v2
- Deprecation Notice: Communicate breaking changes in advance
API-Version: 1.0
Supported-Versions: 1.0, 1.1
Deprecated-Versions:
Sunset-Date: 2025-12-31curl -X POST https://yourdomain.com/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{
"email": "user@example.com",
"password": "password123"
}'curl -X GET https://yourdomain.com/api/v1/users \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json"curl -X POST https://yourdomain.com/api/v1/users \
-H "Authorization: Bearer YOUR_ADMIN_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "New User",
"email": "newuser@example.com",
"password": "securePassword123",
"role": "USER"
}'---
Document Version: 1.1
Last Updated: December 8, 2024
API Version: v1.0
Next Review: January 31, 2025