{"openapi":"3.0.0","paths":{"/api/v1/auth/login":{"post":{"operationId":"AuthController_login","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginDto"}}}},"responses":{"200":{"description":""}},"summary":"Admin login","tags":["Authentication"]}},"/api/v1/auth/refresh":{"post":{"operationId":"AuthController_refreshTokens","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshTokenDto"}}}},"responses":{"200":{"description":""}},"summary":"Refresh access token","tags":["Authentication"]}},"/api/v1/auth/logout":{"post":{"operationId":"AuthController_logout","parameters":[],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Admin logout","tags":["Authentication"]}},"/api/v1/auth/profile":{"get":{"operationId":"AuthController_getProfile","parameters":[],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Get current user profile","tags":["Authentication"]}},"/api/v1/auth/onboarding/complete-super-admin":{"post":{"operationId":"AuthController_completeSuperAdminOnboarding","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompleteSuperAdminOnboardingDto"}}}},"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"One-time super admin account setup","tags":["Authentication"]}},"/api/v1/auth/change-password":{"post":{"operationId":"AuthController_changePassword","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChangePasswordDto"}}}},"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Change password (authenticated)","tags":["Authentication"]}},"/api/v1/auth/forgot-password":{"post":{"operationId":"AuthController_forgotPassword","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordDto"}}}},"responses":{"200":{"description":""}},"summary":"Request password reset OTP via email","tags":["Authentication"]}},"/api/v1/auth/verify-otp":{"post":{"operationId":"AuthController_verifyOtp","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyOtpDto"}}}},"responses":{"200":{"description":""}},"summary":"Verify OTP and receive reset token","tags":["Authentication"]}},"/api/v1/auth/reset-password":{"post":{"operationId":"AuthController_resetPassword","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordDto"}}}},"responses":{"200":{"description":""}},"summary":"Reset password with verified token","tags":["Authentication"]}},"/api/v1/auth/change-email/request":{"post":{"operationId":"AuthController_requestEmailChange","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestEmailChangeDto"}}}},"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Request admin email change (recovery PIN + new email)","tags":["Authentication"]}},"/api/v1/auth/change-email/confirm":{"post":{"operationId":"AuthController_confirmEmailChange","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmEmailChangeDto"}}}},"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Confirm admin email change with OTP sent to new email","tags":["Authentication"]}},"/api/v1/users":{"post":{"description":"Creates a new admin user account. Only Super Admins can create new users.","operationId":"UsersController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateUserDto"}}}},"responses":{"201":{"description":"User created successfully","content":{"application/json":{"schema":{"example":{"success":true,"data":{"id":"64a1b2c3d4e5f6789012abcd","fullName":"John Doe","email":"john@teruf.org","role":"content_admin","isActive":true,"createdAt":"2024-01-01T00:00:00.000Z"}}}}}},"400":{"description":"Validation error"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Insufficient permissions"},"409":{"description":"Conflict - Email already exists"}},"security":[{"bearer":[]}],"summary":"Create a new admin user","tags":["Users"]},"get":{"description":"Retrieves a paginated list of all admin users. Only Super Admins can access this endpoint.","operationId":"UsersController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"minimum":1,"default":1,"example":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Items per page","schema":{"minimum":1,"maximum":100,"default":10,"example":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search by name or email","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Field to sort by","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"enum":["asc","desc"],"type":"string"}}],"responses":{"200":{"description":"Users retrieved successfully","content":{"application/json":{"schema":{"example":{"success":true,"data":{"data":[{"id":"64a1b2c3d4e5f6789012abcd","fullName":"John Doe","email":"john@teruf.org","role":"content_admin","isActive":true}],"meta":{"total":10,"page":1,"limit":10,"totalPages":1,"hasNextPage":false,"hasPrevPage":false}}}}}}}},"security":[{"bearer":[]}],"summary":"Get all admin users","tags":["Users"]}},"/api/v1/users/{id}":{"get":{"description":"Retrieves details of a specific admin user by ID.","operationId":"UsersController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"User ID","schema":{"example":"64a1b2c3d4e5f6789012abcd","type":"string"}}],"responses":{"200":{"description":"User retrieved successfully"},"404":{"description":"User not found"}},"security":[{"bearer":[]}],"summary":"Get a single admin user","tags":["Users"]},"patch":{"description":"Updates an existing admin user. Only Super Admins can update users.","operationId":"UsersController_update","parameters":[{"name":"id","required":true,"in":"path","description":"User ID","schema":{"example":"64a1b2c3d4e5f6789012abcd","type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUserDto"}}}},"responses":{"200":{"description":"User updated successfully"},"404":{"description":"User not found"},"409":{"description":"Conflict - Email already exists"}},"security":[{"bearer":[]}],"summary":"Update an admin user","tags":["Users"]},"delete":{"description":"Soft deletes an admin user. Cannot delete the last super admin.","operationId":"UsersController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"User ID","schema":{"example":"64a1b2c3d4e5f6789012abcd","type":"string"}}],"responses":{"200":{"description":"User deleted successfully"},"400":{"description":"Cannot delete the last super admin"},"404":{"description":"User not found"}},"security":[{"bearer":[]}],"summary":"Delete an admin user","tags":["Users"]}},"/api/v1/site-settings":{"get":{"description":"Retrieves the current site settings including logo, colors, contact info, and SEO data. Public endpoint.","operationId":"SiteSettingsController_getSettings","parameters":[],"responses":{"200":{"description":"Site settings retrieved successfully","content":{"application/json":{"schema":{"example":{"success":true,"data":{"logoText":"TERUF","logoTagline":"Universal Foundation","primaryColor":"#064E3B","accentColor":"#D4AF37","organizationName":"The Elizabeth Resources Universal Foundation","email":"Officialteruf@gmail.com","phone1":"08084771044","address":{"street":"House 42, 221 Crescent, Off Road 22","city":"Abuja","country":"Nigeria"}}}}}}}},"summary":"Get site settings","tags":["Site Settings"]},"patch":{"description":"Updates site settings. Only Super Admins can modify site settings.","operationId":"SiteSettingsController_updateSettings","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSiteSettingsDto"}}}},"responses":{"200":{"description":"Site settings updated successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Super Admin only"}},"security":[{"bearer":[]}],"summary":"Update site settings","tags":["Site Settings"]}},"/api/v1/upload/image":{"post":{"description":"Uploads an image to Cloudinary. Supported formats: JPEG, PNG, GIF, WebP. Max size: 10MB","operationId":"UploadController_uploadImage","parameters":[],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"Image file to upload"},"folder":{"type":"string","description":"Subfolder for organization (default: general)","example":"gallery"}},"required":["file"]}}}},"responses":{"201":{"description":"Image uploaded successfully","content":{"application/json":{"schema":{"example":{"success":true,"data":{"url":"https://res.cloudinary.com/xxx/image/upload/v1234567890/teruf/gallery/image.jpg","publicId":"teruf/gallery/image","format":"jpg","width":1920,"height":1080,"bytes":245678,"resourceType":"image"}}}}}},"400":{"description":"Invalid file type or size"},"401":{"description":"Unauthorized"}},"security":[{"bearer":[]}],"summary":"Upload an image","tags":["File Upload"]}},"/api/v1/upload/video":{"post":{"description":"Uploads a video to Cloudinary. Supported formats: MP4, WebM, QuickTime. Max size: 100MB","operationId":"UploadController_uploadVideo","parameters":[],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"Video file to upload"},"folder":{"type":"string","description":"Subfolder for organization","example":"videos"}},"required":["file"]}}}},"responses":{"201":{"description":"Video uploaded successfully","content":{"application/json":{"schema":{"example":{"success":true,"data":{"url":"https://res.cloudinary.com/xxx/video/upload/v1234567890/teruf/videos/video.mp4","publicId":"teruf/videos/video","format":"mp4","width":1920,"height":1080,"bytes":12345678,"resourceType":"video"}}}}}},"400":{"description":"Invalid file type or size"}},"security":[{"bearer":[]}],"summary":"Upload a video","tags":["File Upload"]}},"/api/v1/upload/document":{"post":{"description":"Uploads a document to Cloudinary. Supported formats: PDF, DOC, DOCX. Max size: 25MB","operationId":"UploadController_uploadDocument","parameters":[],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary","description":"Document file to upload"},"folder":{"type":"string","description":"Subfolder for organization","example":"documents"}},"required":["file"]}}}},"responses":{"201":{"description":"Document uploaded successfully"},"400":{"description":"Invalid file type or size"}},"security":[{"bearer":[]}],"summary":"Upload a document","tags":["File Upload"]}},"/api/v1/upload/{publicId}":{"delete":{"description":"Deletes a file from Cloudinary by its public ID","operationId":"UploadController_deleteFile","parameters":[{"name":"publicId","required":true,"in":"path","description":"Cloudinary public ID (URL encoded)","schema":{"example":"teruf%2Fgallery%2Fimage","type":"string"}},{"name":"resourceType","required":true,"in":"query","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"resourceType":{"type":"string","enum":["image","video","raw"],"default":"image","description":"Type of resource"}}}}}},"responses":{"200":{"description":"File deleted successfully","content":{"application/json":{"schema":{"example":{"success":true,"data":{"message":"File deleted successfully"}}}}}},"400":{"description":"Failed to delete file"}},"security":[{"bearer":[]}],"summary":"Delete a file","tags":["File Upload"]}},"/api/v1/mail/compose":{"post":{"description":"Composes and sends a branded TERUF email to any recipient via SMTP. The recipient does not need to be a newsletter subscriber.","operationId":"MailController_compose","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendDirectEmailDto"}}}},"responses":{"201":{"description":"Email sent successfully"},"400":{"description":"SMTP not configured or send failed"}},"security":[{"bearer":[]}],"summary":"Send a direct email to any address","tags":["Mail"]}},"/api/v1/hero":{"get":{"description":"Retrieves the hero section content including tagline, title, description, and media. Public endpoint.","operationId":"HeroController_getHero","parameters":[],"responses":{"200":{"description":"Hero content retrieved successfully","content":{"application/json":{"schema":{"example":{"success":true,"data":{"tagline":"Empowering Minds & Enriching Relationships","title":"Preserving Healthy Sexual Values & Family Integrity","description":"The Elizabeth Resources Universal Foundation...","mediaType":"video","videoUrl":"https://example.com/video.mp4","imageUrl":"https://example.com/image.jpg"}}}}}}},"summary":"Get hero section content","tags":["Hero Section"]},"patch":{"description":"Updates the hero section content. Only Super Admins can modify hero content.","operationId":"HeroController_updateHero","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateHeroDto"}}}},"responses":{"200":{"description":"Hero section updated successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Super Admin only"}},"security":[{"bearer":[]}],"summary":"Update hero section","tags":["Hero Section"]}},"/api/v1/hero/sync-gallery":{"post":{"description":"Creates or updates a gallery item for the current hero video.","operationId":"HeroController_syncHeroGallery","parameters":[],"responses":{"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Sync hero video to gallery","tags":["Hero Section"]}},"/api/v1/gallery":{"post":{"description":"Admin access required.","operationId":"GalleryController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateGalleryItemDto"}}}},"responses":{"201":{"description":"Gallery item created successfully"}},"security":[{"bearer":[]}],"summary":"Create a new gallery item","tags":["Gallery"]},"get":{"description":"Public endpoint.","operationId":"GalleryController_findAll","parameters":[{"name":"category","required":false,"in":"query","description":"Filter by category","schema":{}}],"responses":{"200":{"description":"Gallery items retrieved successfully"}},"summary":"Get all gallery items (paginated)","tags":["Gallery"]}},"/api/v1/gallery/active":{"get":{"description":"Public endpoint.","operationId":"GalleryController_findAllActive","parameters":[],"responses":{"200":{"description":""}},"summary":"Get all active gallery items","tags":["Gallery"]}},"/api/v1/gallery/mine":{"get":{"operationId":"GalleryController_findMine","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"minimum":1,"maximum":100,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Get gallery items created by current user","tags":["Gallery"]}},"/api/v1/gallery/categories":{"get":{"description":"Public endpoint.","operationId":"GalleryController_getCategories","parameters":[],"responses":{"200":{"description":""}},"summary":"Get all gallery categories","tags":["Gallery"]}},"/api/v1/gallery/{id}/download":{"get":{"operationId":"GalleryController_download","parameters":[{"name":"id","required":true,"in":"path","description":"Gallery item ID","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Download gallery media (increments counter, redirects)","tags":["Gallery"]}},"/api/v1/gallery/{id}":{"get":{"operationId":"GalleryController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Gallery item ID","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Get a single gallery item","tags":["Gallery"]},"patch":{"description":"Admin access required.","operationId":"GalleryController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateGalleryItemDto"}}}},"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Update a gallery item","tags":["Gallery"]},"delete":{"description":"Admin access required.","operationId":"GalleryController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Delete a gallery item","tags":["Gallery"]}},"/api/v1/services":{"post":{"description":"Creates a new service offering. Super Admin only.","operationId":"ServicesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateServiceDto"}}}},"responses":{"201":{"description":"Service created successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - Super Admin only"}},"security":[{"bearer":[]}],"summary":"Create a new service","tags":["Services"]},"get":{"description":"Retrieves a paginated list of services. Public endpoint.","operationId":"ServicesController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"minimum":1,"maximum":100,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"Services retrieved successfully"}},"summary":"Get all services (paginated)","tags":["Services"]}},"/api/v1/services/active":{"get":{"description":"Retrieves all active services ordered by display order. Public endpoint.","operationId":"ServicesController_findAllActive","parameters":[],"responses":{"200":{"description":"Active services retrieved successfully"}},"summary":"Get all active services","tags":["Services"]}},"/api/v1/services/{id}":{"get":{"description":"Retrieves a specific service by ID. Public endpoint.","operationId":"ServicesController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Service ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Service retrieved successfully"},"404":{"description":"Service not found"}},"summary":"Get a single service","tags":["Services"]},"patch":{"description":"Updates an existing service. Super Admin only.","operationId":"ServicesController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Service ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateServiceDto"}}}},"responses":{"200":{"description":"Service updated successfully"},"404":{"description":"Service not found"}},"security":[{"bearer":[]}],"summary":"Update a service","tags":["Services"]},"delete":{"description":"Soft deletes a service. Super Admin only.","operationId":"ServicesController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"Service ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Service deleted successfully"},"404":{"description":"Service not found"}},"security":[{"bearer":[]}],"summary":"Delete a service","tags":["Services"]}},"/api/v1/services/reorder":{"post":{"description":"Updates the display order of services. Super Admin only.","operationId":"ServicesController_reorder","parameters":[],"responses":{"200":{"description":"Services reordered successfully"}},"security":[{"bearer":[]}],"summary":"Reorder services","tags":["Services"]}},"/api/v1/programs":{"post":{"description":"Creates a new program/event. Admin access required.","operationId":"ProgramsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProgramDto"}}}},"responses":{"201":{"description":"Program created successfully"}},"security":[{"bearer":[]}],"summary":"Create a new program","tags":["Programs"]},"get":{"description":"Retrieves a paginated list of programs. Public endpoint.","operationId":"ProgramsController_findAll","parameters":[{"name":"type","required":false,"in":"query","schema":{"enum":["seminar","conference","training","outreach","campaign","workshop"],"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"enum":["current","upcoming","past"],"type":"string"}}],"responses":{"200":{"description":"Programs retrieved successfully"}},"summary":"Get all programs (paginated)","tags":["Programs"]}},"/api/v1/programs/active":{"get":{"description":"Retrieves all active programs. Public endpoint.","operationId":"ProgramsController_findAllActive","parameters":[],"responses":{"200":{"description":"Active programs retrieved successfully"}},"summary":"Get all active programs","tags":["Programs"]}},"/api/v1/programs/status/{status}":{"get":{"description":"Retrieves programs filtered by status. Public endpoint.","operationId":"ProgramsController_findByStatus","parameters":[{"name":"status","required":true,"in":"path","schema":{"enum":["current","upcoming","past"],"type":"string"}}],"responses":{"200":{"description":"Programs retrieved successfully"}},"summary":"Get programs by status","tags":["Programs"]}},"/api/v1/programs/{id}":{"get":{"description":"Retrieves a specific program by ID. Public endpoint.","operationId":"ProgramsController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Program ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Program retrieved successfully"},"404":{"description":"Program not found"}},"summary":"Get a single program","tags":["Programs"]},"patch":{"description":"Updates an existing program. Admin access required.","operationId":"ProgramsController_update","parameters":[{"name":"id","required":true,"in":"path","description":"Program ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateProgramDto"}}}},"responses":{"200":{"description":"Program updated successfully"},"404":{"description":"Program not found"}},"security":[{"bearer":[]}],"summary":"Update a program","tags":["Programs"]},"delete":{"description":"Soft deletes a program. Admin access required.","operationId":"ProgramsController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"Program ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Program deleted successfully"},"404":{"description":"Program not found"}},"security":[{"bearer":[]}],"summary":"Delete a program","tags":["Programs"]}},"/api/v1/resources":{"post":{"operationId":"ResourcesController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateResourceDto"}}}},"responses":{"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Create a new resource","tags":["Resources (Articles/Blog)"]},"get":{"operationId":"ResourcesController_findAll","parameters":[{"name":"isPaid","required":false,"in":"query","schema":{"enum":["true","false"],"type":"string"}},{"name":"category","required":false,"in":"query","schema":{"enum":["article","guide","research","video"],"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Get all resources (paginated)","tags":["Resources (Articles/Blog)"]}},"/api/v1/resources/mine":{"get":{"operationId":"ResourcesController_findMine","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"minimum":1,"maximum":100,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Get resources owned by the current admin","tags":["Resources (Articles/Blog)"]}},"/api/v1/resources/active":{"get":{"operationId":"ResourcesController_findAllActive","parameters":[],"responses":{"200":{"description":""}},"tags":["Resources (Articles/Blog)"]}},"/api/v1/resources/featured":{"get":{"operationId":"ResourcesController_findFeatured","parameters":[],"responses":{"200":{"description":""}},"tags":["Resources (Articles/Blog)"]}},"/api/v1/resources/category/{category}":{"get":{"operationId":"ResourcesController_findByCategory","parameters":[{"name":"category","required":true,"in":"path","schema":{"enum":["article","guide","research","video"],"type":"string"}}],"responses":{"200":{"description":""}},"tags":["Resources (Articles/Blog)"]}},"/api/v1/resources/{id}/file":{"get":{"description":"Proxies the attached Cloudinary document/video so the browser receives the real file with a proper filename and extension.","operationId":"ResourcesController_downloadFile","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Download the resource file from Cloudinary","tags":["Resources (Articles/Blog)"]}},"/api/v1/resources/{id}":{"get":{"operationId":"ResourcesController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"tags":["Resources (Articles/Blog)"]},"patch":{"operationId":"ResourcesController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateResourceDto"}}}},"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"tags":["Resources (Articles/Blog)"]},"delete":{"operationId":"ResourcesController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"tags":["Resources (Articles/Blog)"]}},"/api/v1/resources/{id}/download":{"post":{"operationId":"ResourcesController_trackDownload","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"tags":["Resources (Articles/Blog)"]}},"/api/v1/testimonials":{"post":{"operationId":"TestimonialsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTestimonialDto"}}}},"responses":{"201":{"description":"Testimonial created successfully"}},"security":[{"bearer":[]}],"summary":"Create a testimonial (admin — published immediately)","tags":["Testimonials"]},"get":{"operationId":"TestimonialsController_findAll","parameters":[{"name":"status","required":false,"in":"query","schema":{"enum":["pending","approved","rejected"],"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Get all testimonials (admin, paginated)","tags":["Testimonials"]}},"/api/v1/testimonials/submit":{"post":{"description":"Public endpoint. Creates a pending testimonial that admins must approve before it appears on the homepage.","operationId":"TestimonialsController_submit","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitTestimonialDto"}}}},"responses":{"201":{"description":"Testimonial submitted for review"}},"summary":"Submit a testimonial for review","tags":["Testimonials"]}},"/api/v1/testimonials/active":{"get":{"description":"Public endpoint for homepage carousel.","operationId":"TestimonialsController_findAllActive","parameters":[],"responses":{"200":{"description":""}},"summary":"Get approved active testimonials","tags":["Testimonials"]}},"/api/v1/testimonials/{id}":{"get":{"operationId":"TestimonialsController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Testimonial ID","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Get a single testimonial (admin)","tags":["Testimonials"]},"patch":{"operationId":"TestimonialsController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTestimonialDto"}}}},"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Update a testimonial","tags":["Testimonials"]},"delete":{"operationId":"TestimonialsController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Delete a testimonial","tags":["Testimonials"]}},"/api/v1/testimonials/{id}/approve":{"patch":{"operationId":"TestimonialsController_approve","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Approve a pending testimonial for homepage display","tags":["Testimonials"]}},"/api/v1/testimonials/{id}/reject":{"patch":{"operationId":"TestimonialsController_reject","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Reject a pending testimonial","tags":["Testimonials"]}},"/api/v1/team":{"post":{"description":"Super Admin only.","operationId":"TeamController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTeamMemberDto"}}}},"responses":{"201":{"description":"Team member created successfully"}},"security":[{"bearer":[]}],"summary":"Create a new team member","tags":["Team Members"]},"get":{"description":"Public endpoint.","operationId":"TeamController_findAll","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"minimum":1,"maximum":100,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"Team members retrieved successfully"}},"summary":"Get all team members (paginated)","tags":["Team Members"]}},"/api/v1/team/active":{"get":{"description":"Public endpoint.","operationId":"TeamController_findAllActive","parameters":[],"responses":{"200":{"description":""}},"summary":"Get all active team members","tags":["Team Members"]}},"/api/v1/team/admin/all":{"get":{"description":"Super Admin only. No pagination.","operationId":"TeamController_findAllForAdmin","parameters":[],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Get all team members for admin","tags":["Team Members"]}},"/api/v1/team/{id}":{"get":{"operationId":"TeamController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Team member ID","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Get a single team member","tags":["Team Members"]},"patch":{"description":"Super Admin only.","operationId":"TeamController_update","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTeamMemberDto"}}}},"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Update a team member","tags":["Team Members"]},"delete":{"description":"Super Admin only.","operationId":"TeamController_remove","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Delete a team member","tags":["Team Members"]}},"/api/v1/volunteers":{"post":{"description":"Allows public users to submit a volunteer application. Public endpoint.","operationId":"VolunteersController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateVolunteerDto"}}}},"responses":{"201":{"description":"Application submitted successfully"},"400":{"description":"Validation error"}},"summary":"Submit volunteer application","tags":["Volunteers"]},"get":{"description":"Retrieves all volunteer applications. Admin access required.","operationId":"VolunteersController_findAll","parameters":[{"name":"status","required":false,"in":"query","schema":{"enum":["Pending","Approved","Rejected"],"type":"string"}}],"responses":{"200":{"description":"Applications retrieved successfully"}},"security":[{"bearer":[]}],"summary":"Get all volunteer applications","tags":["Volunteers"]}},"/api/v1/volunteers/stats":{"get":{"description":"Retrieves volunteer application statistics. Admin access required.","operationId":"VolunteersController_getStats","parameters":[],"responses":{"200":{"description":"Statistics retrieved successfully"}},"security":[{"bearer":[]}],"summary":"Get volunteer statistics","tags":["Volunteers"]}},"/api/v1/volunteers/published":{"get":{"description":"Public showcase of approved volunteers.","operationId":"VolunteersController_findPublished","parameters":[],"responses":{"200":{"description":""}},"summary":"Get published volunteer profiles","tags":["Volunteers"]}},"/api/v1/volunteers/{id}":{"get":{"description":"Retrieves a specific volunteer application. Admin access required.","operationId":"VolunteersController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Volunteer ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Application retrieved successfully"},"404":{"description":"Application not found"}},"security":[{"bearer":[]}],"summary":"Get a single volunteer application","tags":["Volunteers"]},"delete":{"description":"Soft deletes a volunteer application. Super Admin only.","operationId":"VolunteersController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"Volunteer ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Application deleted successfully"},"404":{"description":"Application not found"}},"security":[{"bearer":[]}],"summary":"Delete a volunteer application","tags":["Volunteers"]}},"/api/v1/volunteers/{id}/status":{"patch":{"description":"Approves, rejects, or sets pending status for a volunteer application. Admin access required.","operationId":"VolunteersController_updateStatus","parameters":[{"name":"id","required":true,"in":"path","description":"Volunteer ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateVolunteerStatusDto"}}}},"responses":{"200":{"description":"Status updated successfully"},"404":{"description":"Application not found"}},"security":[{"bearer":[]}],"summary":"Update volunteer application status","tags":["Volunteers"]}},"/api/v1/volunteers/{id}/profile":{"patch":{"operationId":"VolunteersController_updateProfile","parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateVolunteerProfileDto"}}}},"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"Update volunteer public profile (photo, role, publish)","tags":["Volunteers"]}},"/api/v1/donations":{"post":{"description":"Records a new donation from the public donation page. Public endpoint.","operationId":"DonationsController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateDonationDto"}}}},"responses":{"201":{"description":"Donation recorded successfully"},"400":{"description":"Validation error"}},"summary":"Record a donation","tags":["Donations"]},"get":{"description":"Retrieves all donations. Super Admin only.","operationId":"DonationsController_findAll","parameters":[{"name":"frequency","required":false,"in":"query","schema":{"enum":["one-time","monthly","quarterly","annually"],"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"enum":["pending","completed","failed","refunded"],"type":"string"}}],"responses":{"200":{"description":"Donations retrieved successfully"}},"security":[{"bearer":[]}],"summary":"Get all donations","tags":["Donations"]}},"/api/v1/donations/paystack/initialize":{"post":{"operationId":"DonationsController_initializePaystack","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InitializeDonationPaymentDto"}}}},"responses":{"201":{"description":""}},"summary":"Initialize a Paystack donation payment","tags":["Donations"]}},"/api/v1/donations/paystack/config":{"get":{"operationId":"DonationsController_getPaystackConfig","parameters":[],"responses":{"200":{"description":""}},"summary":"Check whether Paystack is configured for donations","tags":["Donations"]}},"/api/v1/donations/paystack/verify/{reference}":{"get":{"operationId":"DonationsController_verifyPaystack","parameters":[{"name":"reference","required":true,"in":"path","description":"Paystack payment reference","schema":{"type":"string"}}],"responses":{"200":{"description":""}},"summary":"Verify a Paystack donation payment","tags":["Donations"]}},"/api/v1/donations/stats":{"get":{"description":"Retrieves donation statistics. Super Admin only.","operationId":"DonationsController_getStats","parameters":[],"responses":{"200":{"description":"Statistics retrieved successfully"}},"security":[{"bearer":[]}],"summary":"Get donation statistics","tags":["Donations"]}},"/api/v1/donations/recent":{"get":{"description":"Retrieves recent completed donations. Super Admin only.","operationId":"DonationsController_getRecent","parameters":[{"name":"limit","required":false,"in":"query","schema":{"example":5,"type":"number"}}],"responses":{"200":{"description":"Recent donations retrieved successfully"}},"security":[{"bearer":[]}],"summary":"Get recent donations","tags":["Donations"]}},"/api/v1/donations/{id}":{"get":{"description":"Retrieves a specific donation. Super Admin only.","operationId":"DonationsController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Donation ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Donation retrieved successfully"},"404":{"description":"Donation not found"}},"security":[{"bearer":[]}],"summary":"Get a single donation","tags":["Donations"]},"delete":{"description":"Soft deletes a donation record. Super Admin only.","operationId":"DonationsController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"Donation ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Donation deleted successfully"},"404":{"description":"Donation not found"}},"security":[{"bearer":[]}],"summary":"Delete a donation record","tags":["Donations"]}},"/api/v1/donations/{id}/status":{"patch":{"description":"Updates the status of a donation. Super Admin only.","operationId":"DonationsController_updateStatus","parameters":[{"name":"id","required":true,"in":"path","description":"Donation ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateDonationStatusDto"}}}},"responses":{"200":{"description":"Status updated successfully"},"404":{"description":"Donation not found"}},"security":[{"bearer":[]}],"summary":"Update donation status","tags":["Donations"]}},"/api/v1/contact":{"post":{"description":"Allows public users to submit a contact inquiry. Public endpoint.","operationId":"ContactController_create","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContactMessageDto"}}}},"responses":{"201":{"description":"Message submitted successfully"},"400":{"description":"Validation error"}},"summary":"Submit a contact message","tags":["Contact Messages"]},"get":{"description":"Retrieves all contact messages. Admin access required.","operationId":"ContactController_findAll","parameters":[{"name":"type","required":false,"in":"query","schema":{"enum":["inbox","consultation"],"type":"string"}},{"name":"status","required":false,"in":"query","schema":{"enum":["new","read","replied","resolved","archived"],"type":"string"}}],"responses":{"200":{"description":"Messages retrieved successfully"}},"security":[{"bearer":[]}],"summary":"Get all contact messages","tags":["Contact Messages"]}},"/api/v1/contact/stats":{"get":{"description":"Retrieves contact message statistics. Admin access required.","operationId":"ContactController_getStats","parameters":[],"responses":{"200":{"description":"Statistics retrieved successfully"}},"security":[{"bearer":[]}],"summary":"Get contact message statistics","tags":["Contact Messages"]}},"/api/v1/contact/{id}":{"get":{"description":"Retrieves a specific contact message. Admin access required.","operationId":"ContactController_findOne","parameters":[{"name":"id","required":true,"in":"path","description":"Message ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Message retrieved successfully"},"404":{"description":"Message not found"}},"security":[{"bearer":[]}],"summary":"Get a single contact message","tags":["Contact Messages"]},"delete":{"description":"Soft deletes a contact message. Super Admin only.","operationId":"ContactController_remove","parameters":[{"name":"id","required":true,"in":"path","description":"Message ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Message deleted successfully"},"404":{"description":"Message not found"}},"security":[{"bearer":[]}],"summary":"Delete a contact message","tags":["Contact Messages"]}},"/api/v1/contact/{id}/status":{"patch":{"description":"Updates the status of a contact message. Admin access required.","operationId":"ContactController_updateStatus","parameters":[{"name":"id","required":true,"in":"path","description":"Message ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContactMessageStatusDto"}}}},"responses":{"200":{"description":"Status updated successfully"},"404":{"description":"Message not found"}},"security":[{"bearer":[]}],"summary":"Update contact message status","tags":["Contact Messages"]}},"/api/v1/contact/{id}/reply":{"post":{"description":"Sends an SMTP reply email to the sender and stores it in the conversation thread.","operationId":"ContactController_reply","parameters":[{"name":"id","required":true,"in":"path","description":"Message ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplyContactMessageDto"}}}},"responses":{"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Reply to a contact message","tags":["Contact Messages"]}},"/api/v1/newsletter/subscribe":{"post":{"description":"Allows public users to subscribe to the newsletter. Public endpoint.","operationId":"NewsletterController_subscribe","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeDto"}}}},"responses":{"201":{"description":"Subscribed successfully"},"409":{"description":"Email already subscribed"}},"summary":"Subscribe to newsletter","tags":["Newsletter"]}},"/api/v1/newsletter/unsubscribe":{"post":{"description":"Allows users to unsubscribe from the newsletter. Public endpoint.","operationId":"NewsletterController_unsubscribe","parameters":[],"responses":{"200":{"description":"Unsubscribed successfully"},"404":{"description":"Subscriber not found"}},"summary":"Unsubscribe from newsletter","tags":["Newsletter"]}},"/api/v1/newsletter/subscribers":{"get":{"description":"Retrieves all newsletter subscribers. Admin access required.","operationId":"NewsletterController_findAllSubscribers","parameters":[{"name":"isActive","required":false,"in":"query","schema":{"enum":["true","false"],"type":"string"}}],"responses":{"200":{"description":"Subscribers retrieved successfully"}},"security":[{"bearer":[]}],"summary":"Get all subscribers","tags":["Newsletter"]}},"/api/v1/newsletter/subscribers/{id}":{"patch":{"description":"Updates a subscriber record. Admin access required.","operationId":"NewsletterController_updateSubscriber","parameters":[{"name":"id","required":true,"in":"path","description":"Subscriber ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSubscriberDto"}}}},"responses":{"200":{"description":"Subscriber updated successfully"},"404":{"description":"Subscriber not found"}},"security":[{"bearer":[]}],"summary":"Update subscriber","tags":["Newsletter"]},"delete":{"description":"Soft deletes a subscriber. Super Admin only.","operationId":"NewsletterController_removeSubscriber","parameters":[{"name":"id","required":true,"in":"path","description":"Subscriber ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Subscriber deleted successfully"},"404":{"description":"Subscriber not found"}},"security":[{"bearer":[]}],"summary":"Delete subscriber","tags":["Newsletter"]}},"/api/v1/newsletter/broadcasts":{"post":{"description":"Creates and sends a newsletter broadcast to all active subscribers. Admin access required.","operationId":"NewsletterController_createBroadcast","parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBroadcastDto"}}}},"responses":{"201":{"description":"Broadcast sent successfully"}},"security":[{"bearer":[]}],"summary":"Create and send broadcast","tags":["Newsletter"]},"get":{"description":"Retrieves all newsletter broadcasts. Admin access required.","operationId":"NewsletterController_findAllBroadcasts","parameters":[{"name":"page","required":false,"in":"query","description":"Page number","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"minimum":1,"maximum":100,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":"Broadcasts retrieved successfully"}},"security":[{"bearer":[]}],"summary":"Get all broadcasts","tags":["Newsletter"]},"delete":{"description":"Soft-deletes all mailing broadcast history logs.","operationId":"NewsletterController_clearBroadcastHistory","parameters":[],"responses":{"200":{"description":"Broadcast history cleared"}},"security":[{"bearer":[]}],"summary":"Clear broadcast history","tags":["Newsletter"]}},"/api/v1/newsletter/broadcasts/{id}":{"get":{"description":"Retrieves a specific broadcast. Admin access required.","operationId":"NewsletterController_findBroadcast","parameters":[{"name":"id","required":true,"in":"path","description":"Broadcast ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Broadcast retrieved successfully"},"404":{"description":"Broadcast not found"}},"security":[{"bearer":[]}],"summary":"Get a single broadcast","tags":["Newsletter"]},"delete":{"description":"Soft deletes a broadcast. Super Admin only.","operationId":"NewsletterController_removeBroadcast","parameters":[{"name":"id","required":true,"in":"path","description":"Broadcast ID","schema":{"type":"string"}}],"responses":{"200":{"description":"Broadcast deleted successfully"},"404":{"description":"Broadcast not found"}},"security":[{"bearer":[]}],"summary":"Delete broadcast","tags":["Newsletter"]}},"/api/v1/newsletter/stats":{"get":{"description":"Retrieves newsletter statistics. Admin access required.","operationId":"NewsletterController_getStats","parameters":[],"responses":{"200":{"description":"Statistics retrieved successfully"}},"security":[{"bearer":[]}],"summary":"Get newsletter statistics","tags":["Newsletter"]}},"/api/v1/resources/{id}/purchase":{"post":{"description":"Records a paid resource purchase and sends a branded confirmation email.","operationId":"PurchasesController_purchase","parameters":[{"name":"id","required":true,"in":"path","description":"Resource ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateResourcePurchaseDto"}}}},"responses":{"201":{"description":"Purchase completed successfully"}},"summary":"Purchase a paid resource","tags":["Resource Purchases"]}},"/api/v1/programs/{id}/book":{"post":{"description":"Registers an attendee for a free program or paid event and sends a branded confirmation email.","operationId":"BookingsController_book","parameters":[{"name":"id","required":true,"in":"path","description":"Program ID","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateProgramBookingDto"}}}},"responses":{"201":{"description":"Booking confirmed successfully"}},"summary":"Book a program or paid event","tags":["Program Bookings"]}},"/api/v1/bookings":{"get":{"operationId":"BookingsAdminController_findAll","parameters":[{"name":"programId","required":false,"in":"query","schema":{}}],"responses":{"200":{"description":"Bookings retrieved"}},"security":[{"bearer":[]}],"summary":"List all program bookings (admin)","tags":["Program Bookings Admin"]}},"/api/v1/bookings/program/{programId}":{"get":{"operationId":"BookingsAdminController_findByProgram","parameters":[{"name":"programId","required":true,"in":"path","description":"Program ID","schema":{"type":"string"}},{"name":"page","required":false,"in":"query","description":"Page number","schema":{"minimum":1,"default":1,"type":"number"}},{"name":"limit","required":false,"in":"query","description":"Number of items per page","schema":{"minimum":1,"maximum":100,"default":10,"type":"number"}},{"name":"search","required":false,"in":"query","description":"Search query","schema":{"type":"string"}},{"name":"sortBy","required":false,"in":"query","description":"Sort field","schema":{"example":"createdAt","type":"string"}},{"name":"sortOrder","required":false,"in":"query","description":"Sort order","schema":{"default":"desc","type":"string","enum":["asc","desc"]}}],"responses":{"200":{"description":""}},"security":[{"bearer":[]}],"summary":"List bookings for a specific program","tags":["Program Bookings Admin"]}},"/api/v1/bookings/{id}/resend-confirmation":{"post":{"operationId":"BookingsAdminController_resendConfirmation","parameters":[{"name":"id","required":true,"in":"path","description":"Booking ID","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Resend booking confirmation email to attendee","tags":["Program Bookings Admin"]}},"/api/v1/bookings/program/{programId}/notify-all":{"post":{"operationId":"BookingsAdminController_notifyAll","parameters":[{"name":"programId","required":true,"in":"path","description":"Program ID","schema":{"type":"string"}}],"responses":{"201":{"description":""}},"security":[{"bearer":[]}],"summary":"Resend confirmation emails to all attendees of a program","tags":["Program Bookings Admin"]}},"/api/v1/events/stream":{"get":{"description":"Pushes cache-invalidation events when CMS content changes so clients refresh without reload.","operationId":"ContentEventsController_stream","parameters":[],"responses":{"200":{"description":""}},"summary":"Live content change stream (SSE)","tags":["Live Updates"]}}},"info":{"title":"TERUF NGO API","description":"\n## The Elizabeth Resources Universal Foundation (TERUF) Backend API\n\nThis API powers the TERUF NGO website and admin dashboard.\n\n### Authentication\n- The **public website** does not require authentication\n- The **Admin Dashboard** is protected with JWT authentication\n- Use the login endpoint to obtain access tokens\n\n### Admin Roles\n- **Super Admin**: Full access to all features including user management, donations, site settings\n- **Content Admin**: Access to content management (articles, resources, programs) and operational data\n\n### Rate Limiting\n- API requests are rate limited to prevent abuse\n- Default: 100 requests per minute\n\n### Response Format\nAll responses follow a consistent format:\n```json\n{\n  \"success\": true,\n  \"data\": { ... },\n  \"timestamp\": \"2024-01-01T00:00:00.000Z\"\n}\n```\n    ","version":"1.0","contact":{}},"tags":[{"name":"Authentication","description":"Admin authentication endpoints"},{"name":"Users","description":"Admin user management (Super Admin only)"},{"name":"Site Settings","description":"Global site configuration"},{"name":"Hero Section","description":"Homepage hero content management"},{"name":"Services","description":"Services/offerings management"},{"name":"Programs","description":"Events and programs management"},{"name":"Resources (Articles/Blog)","description":"Articles, guides, research papers, videos"},{"name":"Testimonials","description":"Client testimonials"},{"name":"Team Members","description":"Team member profiles"},{"name":"Gallery","description":"Photo gallery management"},{"name":"Volunteers","description":"Volunteer applications management"},{"name":"Donations","description":"Donation records management"},{"name":"Contact Messages","description":"Contact form submissions"},{"name":"Newsletter","description":"Newsletter subscribers and broadcasts"},{"name":"File Upload","description":"Cloudinary file upload endpoints"}],"servers":[{"url":"http://localhost:4000","description":"Development Server"},{"url":"https://teruf.org","description":"Production API (via reverse proxy)"}],"components":{"securitySchemes":{"bearer":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"Enter JWT token obtained from /api/v1/auth/login"}},"schemas":{"LoginDto":{"type":"object","properties":{"email":{"type":"string","description":"Admin email address","example":"admin@teruf.org"},"password":{"type":"string","description":"Admin password","example":"SecurePassword123!"}},"required":["email","password"]},"RefreshTokenDto":{"type":"object","properties":{"refreshToken":{"type":"string","description":"Refresh token","example":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}},"required":["refreshToken"]},"CompleteSuperAdminOnboardingDto":{"type":"object","properties":{"fullName":{"type":"string","example":"Elizabeth Okonkwo"},"email":{"type":"string","example":"elizabeth@teruf.org"},"password":{"type":"string","example":"MySecurePass2026!"}},"required":["fullName","email","password"]},"ChangePasswordDto":{"type":"object","properties":{"currentPassword":{"type":"string"},"newPassword":{"type":"string"}},"required":["currentPassword","newPassword"]},"ForgotPasswordDto":{"type":"object","properties":{"email":{"type":"string","example":"admin@teruf.org"}},"required":["email"]},"VerifyOtpDto":{"type":"object","properties":{"email":{"type":"string"},"otp":{"type":"string","example":"123456"}},"required":["email","otp"]},"ResetPasswordDto":{"type":"object","properties":{"resetToken":{"type":"string"},"newPassword":{"type":"string"}},"required":["resetToken","newPassword"]},"RequestEmailChangeDto":{"type":"object","properties":{"recoveryPin":{"type":"string","description":"Recovery PIN configured in EMAIL_RECOVERY_PIN"},"newEmail":{"type":"string","example":"new.admin@teruf.org"}},"required":["recoveryPin","newEmail"]},"ConfirmEmailChangeDto":{"type":"object","properties":{"otp":{"type":"string","example":"123456"}},"required":["otp"]},"CreateUserDto":{"type":"object","properties":{"fullName":{"type":"string","description":"Full name of the admin user","example":"John Doe"},"email":{"type":"string","description":"Email address","example":"john@teruf.org"},"password":{"type":"string","description":"Password (minimum 8 characters)","example":"SecurePass123!"},"role":{"type":"string","description":"User role","enum":["super_admin","content_admin"],"default":"content_admin","example":"content_admin"}},"required":["fullName","email","password"]},"UpdateUserDto":{"type":"object","properties":{"fullName":{"type":"string","description":"Full name of the admin user","example":"John Doe"},"email":{"type":"string","description":"Email address","example":"john@teruf.org"},"password":{"type":"string","description":"Password (minimum 8 characters)","example":"NewSecurePass123!"},"role":{"type":"string","description":"User role","enum":["super_admin","content_admin"],"example":"content_admin"},"isActive":{"type":"boolean","description":"Is user active","example":true},"avatar":{"type":"string","description":"Avatar URL","example":"https://cloudinary.com/avatar.jpg"}}},"AddressDto":{"type":"object","properties":{"street":{"type":"string","example":"House 42, 221 Crescent, Off Road 22"},"estate":{"type":"string","example":"Paradise Hills Estate, 2nd Avenue, ENL/FHA"},"area":{"type":"string","example":"Guzape"},"city":{"type":"string","example":"Abuja"},"country":{"type":"string","example":"Nigeria"}}},"SocialLinksDto":{"type":"object","properties":{"instagram":{"type":"string","example":"Officialteruf_"},"linkedin":{"type":"string","example":"The Elizabeth Resources Universal Foundation"},"facebook":{"type":"string"},"twitter":{"type":"string"},"youtube":{"type":"string"}}},"ContactChannelDto":{"type":"object","properties":{"type":{"type":"string","enum":["email","phone"]},"label":{"type":"string","example":"General Inquiries"},"description":{"type":"string","example":"For partnership and media requests"},"value":{"type":"string","example":"Officialteruf@gmail.com"},"order":{"type":"number"}}},"SocialLinkItemDto":{"type":"object","properties":{"platform":{"type":"string","example":"Instagram"},"url":{"type":"string","example":"https://instagram.com/Officialteruf_"},"order":{"type":"number"}}},"ImageFrameDto":{"type":"object","properties":{"x":{"type":"number","example":0},"y":{"type":"number","example":0},"width":{"type":"number","example":100},"height":{"type":"number","example":100},"zoom":{"type":"number","example":1,"deprecated":true}}},"SectionBannerDto":{"type":"object","properties":{"imageUrl":{"type":"string"},"imagePublicId":{"type":"string"},"alt":{"type":"string"},"imageFrame":{"$ref":"#/components/schemas/ImageFrameDto"}}},"ImpactStatsDto":{"type":"object","properties":{"youth":{"type":"number","example":15430},"couples":{"type":"number","example":1240},"cities":{"type":"number","example":6},"schools":{"type":"number","example":42}}},"SeoDto":{"type":"object","properties":{"metaTitle":{"type":"string","example":"TERUF - The Elizabeth Resources Universal Foundation"},"metaDescription":{"type":"string","example":"Providing professional counseling and sex education across Africa"},"metaKeywords":{"example":["counseling","sex education","family","NGO"],"type":"array","items":{"type":"string"}},"ogImage":{"type":"string"}}},"FounderSpotlightDto":{"type":"object","properties":{"name":{"type":"string","example":"Elizabeth"},"role":{"type":"string","example":"Founder, Lead Family Therapist"},"imageUrl":{"type":"string"},"imageFrame":{"$ref":"#/components/schemas/ImageFrameDto"},"tagline":{"type":"string","example":"Began operations in 2014"},"title":{"type":"string","example":"Founder's Spotlight"},"bio":{"type":"string"}}},"UpdateSiteSettingsDto":{"type":"object","properties":{"logoText":{"type":"string","example":"TERUF"},"logoTagline":{"type":"string","example":"Universal Foundation"},"logoImageUrl":{"type":"string"},"faviconUrl":{"type":"string"},"primaryColor":{"type":"string","example":"#064E3B"},"accentColor":{"type":"string","example":"#D4AF37"},"organizationName":{"type":"string","example":"The Elizabeth Resources Universal Foundation"},"organizationShortName":{"type":"string","example":"TERUF"},"registrationNumber":{"type":"string","example":"CAC/IT/NO 111695"},"email":{"type":"string","example":"Officialteruf@gmail.com"},"phone1":{"type":"string","example":"08084771044"},"phone2":{"type":"string","example":"09079006078"},"address":{"$ref":"#/components/schemas/AddressDto"},"officeHours":{"type":"string","example":"Monday - Friday: 8:00 AM - 5:00 PM (GMT+1)"},"socialLinks":{"$ref":"#/components/schemas/SocialLinksDto"},"contactChannels":{"type":"array","items":{"$ref":"#/components/schemas/ContactChannelDto"}},"socialLinksList":{"type":"array","items":{"$ref":"#/components/schemas/SocialLinkItemDto"}},"teamBanner":{"$ref":"#/components/schemas/SectionBannerDto"},"aboutBanner":{"$ref":"#/components/schemas/SectionBannerDto"},"impactStats":{"$ref":"#/components/schemas/ImpactStatsDto"},"seo":{"$ref":"#/components/schemas/SeoDto"},"founderSpotlight":{"$ref":"#/components/schemas/FounderSpotlightDto"},"isActive":{"type":"boolean"}}},"SendDirectEmailDto":{"type":"object","properties":{"to":{"type":"string","example":"client@example.com"},"subject":{"type":"string","example":"Follow-up from TERUF"},"body":{"type":"string","example":"Hello,\n\nThank you for connecting with TERUF..."},"recipientName":{"type":"string","example":"Adaeze"}},"required":["to","subject","body"]},"UpdateHeroDto":{"type":"object","properties":{"tagline":{"type":"string","example":"Empowering Minds & Enriching Relationships"},"title":{"type":"string","example":"Preserving Healthy Sexual Values & Family Integrity"},"description":{"type":"string","example":"The Elizabeth Resources Universal Foundation (TERUF) provides professional, research-based counseling..."},"mediaType":{"type":"string","enum":["video","image"],"example":"video"},"videoUrl":{"type":"string","example":"https://assets.mixkit.co/videos/preview/mixkit-hands-of-loving-couple.mp4"},"imageUrl":{"type":"string","example":"https://images.unsplash.com/photo-1516589178581.jpg"},"videoPublicId":{"type":"string","example":"teruf/hero/video-id"},"imagePublicId":{"type":"string","example":"teruf/hero/image-id"},"mobileVideoUrl":{"type":"string","example":"https://assets.mixkit.co/videos/preview/mixkit-mobile-portrait-video.mp4"},"mobileVideoPublicId":{"type":"string","example":"teruf/hero/mobile-video-id"},"mobileVideoDuration":{"type":"number","example":12,"description":"Mobile video duration in seconds"},"ctaText":{"type":"string","example":"Get Started"},"ctaLink":{"type":"string","example":"/services"},"secondaryCtaText":{"type":"string","example":"Learn More"},"secondaryCtaLink":{"type":"string","example":"/about"},"videoDuration":{"type":"number","example":30,"description":"Video duration in seconds"},"galleryItemId":{"type":"string","description":"Gallery item ID for full-length video"},"isActive":{"type":"boolean"}}},"CreateGalleryItemDto":{"type":"object","properties":{"title":{"type":"string","example":"Youth Outreach 2026"},"description":{"type":"string","example":"Photos from our annual youth outreach program"},"caption":{"type":"string","example":"Students at the workshop"},"mediaType":{"type":"string","enum":["image","video"],"default":"image"},"imageUrl":{"type":"string","example":"https://cloudinary.com/gallery/image.jpg"},"mediaUrl":{"type":"string","example":"https://cloudinary.com/gallery/video.mp4"},"mediaPublicId":{"type":"string"},"thumbnailUrl":{"type":"string","example":"https://cloudinary.com/gallery/thumbnail.jpg"},"category":{"type":"string","example":"Outreach"},"eventDate":{"type":"string","example":"May 18, 2026"},"duration":{"type":"number","example":45},"order":{"type":"number","example":1},"isActive":{"type":"boolean","default":true}},"required":["title","imageUrl"]},"UpdateGalleryItemDto":{"type":"object","properties":{"title":{"type":"string","example":"Youth Outreach 2026"},"description":{"type":"string","example":"Photos from our annual youth outreach program"},"caption":{"type":"string","example":"Students at the workshop"},"mediaType":{"type":"string","enum":["image","video"],"default":"image"},"imageUrl":{"type":"string","example":"https://cloudinary.com/gallery/image.jpg"},"mediaUrl":{"type":"string","example":"https://cloudinary.com/gallery/video.mp4"},"mediaPublicId":{"type":"string"},"thumbnailUrl":{"type":"string","example":"https://cloudinary.com/gallery/thumbnail.jpg"},"category":{"type":"string","example":"Outreach"},"eventDate":{"type":"string","example":"May 18, 2026"},"duration":{"type":"number","example":45},"order":{"type":"number","example":1},"isActive":{"type":"boolean","default":true}}},"CreateServiceDto":{"type":"object","properties":{"title":{"type":"string","example":"Individual & Sexuality Counselling"},"iconName":{"type":"string","example":"User","description":"Lucide icon name"},"tagline":{"type":"string","example":"Safe, non-judgmental space to heal and grow"},"description":{"type":"string","example":"Our professional counseling sessions address self-discovery..."},"benefits":{"example":["100% confidential environment","Licensed sexual health counsellors"],"type":"array","items":{"type":"string"}},"audience":{"example":["Youths","Adolescents","Adults facing trauma"],"type":"array","items":{"type":"string"}},"ctaLabel":{"type":"string","example":"Schedule Counselling"},"imageUrl":{"type":"string","example":"https://res.cloudinary.com/demo/image/upload/service.jpg"},"imagePublicId":{"type":"string"},"imageFrame":{"$ref":"#/components/schemas/ImageFrameDto"},"order":{"type":"number","example":1,"description":"Display order"},"isActive":{"type":"boolean","default":true}},"required":["title","iconName","tagline","description"]},"UpdateServiceDto":{"type":"object","properties":{"title":{"type":"string","example":"Individual & Sexuality Counselling"},"iconName":{"type":"string","example":"User","description":"Lucide icon name"},"tagline":{"type":"string","example":"Safe, non-judgmental space to heal and grow"},"description":{"type":"string","example":"Our professional counseling sessions address self-discovery..."},"benefits":{"example":["100% confidential environment","Licensed sexual health counsellors"],"type":"array","items":{"type":"string"}},"audience":{"example":["Youths","Adolescents","Adults facing trauma"],"type":"array","items":{"type":"string"}},"ctaLabel":{"type":"string","example":"Schedule Counselling"},"imageUrl":{"type":"string","example":"https://res.cloudinary.com/demo/image/upload/service.jpg"},"imagePublicId":{"type":"string"},"imageFrame":{"$ref":"#/components/schemas/ImageFrameDto"},"order":{"type":"number","example":1,"description":"Display order"},"isActive":{"type":"boolean","default":true}}},"CreateProgramDto":{"type":"object","properties":{"title":{"type":"string","example":"The Informed Adolescent Summit 2026"},"type":{"type":"string","enum":["seminar","conference","training","outreach","campaign","workshop"],"example":"seminar"},"status":{"type":"string","enum":["current","upcoming","past"],"example":"upcoming"},"date":{"type":"string","example":"August 14, 2026"},"startsAt":{"type":"string","example":"2026-08-14T09:00:00.000Z"},"endsAt":{"type":"string","example":"2026-08-14T17:00:00.000Z"},"location":{"type":"string","example":"National Center for Women Development, Abuja"},"description":{"type":"string","example":"Our signature annual youth conference..."},"imageUrl":{"type":"string","example":"https://images.unsplash.com/photo.jpg"},"imagePublicId":{"type":"string"},"imageFrame":{"$ref":"#/components/schemas/ImageFrameDto"},"registrationLink":{"type":"string","example":"https://forms.gle/register"},"capacity":{"type":"number","example":500},"isPaid":{"type":"boolean","example":false,"default":false},"price":{"type":"number","example":25},"currency":{"type":"string","example":"USD","default":"USD"},"order":{"type":"number","example":1},"isActive":{"type":"boolean","default":true}},"required":["title","type","status","date","location","description"]},"UpdateProgramDto":{"type":"object","properties":{"title":{"type":"string","example":"The Informed Adolescent Summit 2026"},"type":{"type":"string","enum":["seminar","conference","training","outreach","campaign","workshop"],"example":"seminar"},"status":{"type":"string","enum":["current","upcoming","past"],"example":"upcoming"},"date":{"type":"string","example":"August 14, 2026"},"startsAt":{"type":"string","example":"2026-08-14T09:00:00.000Z"},"endsAt":{"type":"string","example":"2026-08-14T17:00:00.000Z"},"location":{"type":"string","example":"National Center for Women Development, Abuja"},"description":{"type":"string","example":"Our signature annual youth conference..."},"imageUrl":{"type":"string","example":"https://images.unsplash.com/photo.jpg"},"imagePublicId":{"type":"string"},"imageFrame":{"$ref":"#/components/schemas/ImageFrameDto"},"registrationLink":{"type":"string","example":"https://forms.gle/register"},"capacity":{"type":"number","example":500},"isPaid":{"type":"boolean","example":false,"default":false},"price":{"type":"number","example":25},"currency":{"type":"string","example":"USD","default":"USD"},"order":{"type":"number","example":1},"isActive":{"type":"boolean","default":true}}},"CreateResourceDto":{"type":"object","properties":{"title":{"type":"string","example":"The Parent-Teen Communication Guide"},"category":{"type":"string","enum":["article","guide","research","video"],"example":"guide"},"description":{"type":"string","example":"A highly practical, step-by-step handbook..."},"content":{"type":"string","example":"### Demystifying Difficult Conversations"},"downloadUrl":{"type":"string","example":"https://example.com/downloads/guide.pdf"},"downloadFileName":{"type":"string","example":"parent-teen-communication-guide.pdf"},"downloadPublicId":{"type":"string"},"videoUrl":{"type":"string","example":"https://www.youtube.com/embed/dQw4w9WgXcQ"},"videoPublicId":{"type":"string"},"thumbnailUrl":{"type":"string","example":"https://cloudinary.com/thumbnail.jpg"},"thumbnailPublicId":{"type":"string"},"thumbnailFrame":{"$ref":"#/components/schemas/ImageFrameDto"},"readTime":{"type":"string","example":"8 min read"},"author":{"type":"string","example":"Elizabeth (Founder, TERUF)"},"publishedDate":{"type":"string","example":"June 20, 2026"},"isPaid":{"type":"boolean","example":false},"price":{"type":"number","example":14.99},"tags":{"example":["parenting","communication","teens"],"type":"array","items":{"type":"string"}},"isActive":{"type":"boolean","default":true},"isFeatured":{"type":"boolean","default":false}},"required":["title","category","description","content","readTime","author"]},"UpdateResourceDto":{"type":"object","properties":{"title":{"type":"string","example":"The Parent-Teen Communication Guide"},"category":{"type":"string","enum":["article","guide","research","video"],"example":"guide"},"description":{"type":"string","example":"A highly practical, step-by-step handbook..."},"content":{"type":"string","example":"### Demystifying Difficult Conversations"},"downloadUrl":{"type":"string","example":"https://example.com/downloads/guide.pdf"},"downloadFileName":{"type":"string","example":"parent-teen-communication-guide.pdf"},"downloadPublicId":{"type":"string"},"videoUrl":{"type":"string","example":"https://www.youtube.com/embed/dQw4w9WgXcQ"},"videoPublicId":{"type":"string"},"thumbnailUrl":{"type":"string","example":"https://cloudinary.com/thumbnail.jpg"},"thumbnailPublicId":{"type":"string"},"thumbnailFrame":{"$ref":"#/components/schemas/ImageFrameDto"},"readTime":{"type":"string","example":"8 min read"},"author":{"type":"string","example":"Elizabeth (Founder, TERUF)"},"publishedDate":{"type":"string","example":"June 20, 2026"},"isPaid":{"type":"boolean","example":false},"price":{"type":"number","example":14.99},"tags":{"example":["parenting","communication","teens"],"type":"array","items":{"type":"string"}},"isActive":{"type":"boolean","default":true},"isFeatured":{"type":"boolean","default":false}}},"CreateTestimonialDto":{"type":"object","properties":{"name":{"type":"string","example":"Emeka & Beatrice O."},"role":{"type":"string","example":"Married for 4 Years"},"quote":{"type":"string","example":"We were on the verge of calling off our engagement due to family interference..."},"rating":{"type":"number","example":5,"minimum":1,"maximum":5},"imageUrl":{"type":"string","example":"https://cloudinary.com/testimonial-image.jpg"},"order":{"type":"number","example":1},"isActive":{"type":"boolean","default":true},"status":{"type":"string","enum":["pending","approved","rejected"],"default":"approved"},"submitterEmail":{"type":"string","example":"user@example.com"}},"required":["name","role","quote"]},"SubmitTestimonialDto":{"type":"object","properties":{"name":{"type":"string","example":"Emeka & Beatrice O."},"role":{"type":"string","example":"Married for 4 Years"},"quote":{"type":"string","example":"TERUF helped us rebuild trust in our marriage..."},"rating":{"type":"number","example":5,"minimum":1,"maximum":5},"submitterEmail":{"type":"string","example":"couple@example.com"}},"required":["name","role","quote"]},"UpdateTestimonialDto":{"type":"object","properties":{"name":{"type":"string","example":"Emeka & Beatrice O."},"role":{"type":"string","example":"Married for 4 Years"},"quote":{"type":"string","example":"We were on the verge of calling off our engagement due to family interference..."},"rating":{"type":"number","example":5,"minimum":1,"maximum":5},"imageUrl":{"type":"string","example":"https://cloudinary.com/testimonial-image.jpg"},"order":{"type":"number","example":1},"isActive":{"type":"boolean","default":true},"status":{"type":"string","enum":["pending","approved","rejected"],"default":"approved"},"submitterEmail":{"type":"string","example":"user@example.com"}}},"CreateTeamMemberDto":{"type":"object","properties":{"name":{"type":"string","example":"Elizabeth Kolawole"},"position":{"type":"string","example":"Founder & Lead Counsellor"},"bio":{"type":"string","example":"Elizabeth is a certified relationship counselor with over 20 years of experience..."},"tier":{"type":"string","example":"founder","enum":["founder","board","staff","trustees"]},"imageUrl":{"type":"string","example":"https://cloudinary.com/team-member.jpg"},"imagePublicId":{"type":"string","example":"teruf/team/abc123"},"imageFrame":{"$ref":"#/components/schemas/ImageFrameDto"},"socialLinks":{"$ref":"#/components/schemas/SocialLinksDto"},"order":{"type":"number","example":1},"isActive":{"type":"boolean","default":true}},"required":["name","position"]},"UpdateTeamMemberDto":{"type":"object","properties":{"name":{"type":"string","example":"Elizabeth Kolawole"},"position":{"type":"string","example":"Founder & Lead Counsellor"},"bio":{"type":"string","example":"Elizabeth is a certified relationship counselor with over 20 years of experience..."},"tier":{"type":"string","example":"founder","enum":["founder","board","staff","trustees"]},"imageUrl":{"type":"string","example":"https://cloudinary.com/team-member.jpg"},"imagePublicId":{"type":"string","example":"teruf/team/abc123"},"imageFrame":{"$ref":"#/components/schemas/ImageFrameDto"},"socialLinks":{"$ref":"#/components/schemas/SocialLinksDto"},"order":{"type":"number","example":1},"isActive":{"type":"boolean","default":true}}},"CreateVolunteerDto":{"type":"object","properties":{"fullName":{"type":"string","example":"Sandra Alabi"},"email":{"type":"string","example":"sandra.alabi@gmail.com"},"phone":{"type":"string","example":"08139401234"},"skills":{"example":["Social Media & Design","Event Organizing"],"type":"array","items":{"type":"string"}},"availability":{"type":"string","example":"Part-time (Weekends)"},"interestAreas":{"example":["Menstrual Hygiene Outreaches","Digital Content Production"],"type":"array","items":{"type":"string"}},"cvUrl":{"type":"string","example":"https://cloudinary.com/cv.pdf"},"cvName":{"type":"string","example":"sandra_alabi_resume.pdf"}},"required":["fullName","email","phone","availability"]},"UpdateVolunteerStatusDto":{"type":"object","properties":{"status":{"type":"string","enum":["Pending","Approved","Rejected"],"example":"Approved"},"notes":{"type":"string","example":"Great candidate with relevant experience"}},"required":["status"]},"UpdateVolunteerProfileDto":{"type":"object","properties":{"volunteerRole":{"type":"string","example":"Counseling Support Lead"},"photoUrl":{"type":"string","example":"https://res.cloudinary.com/..."},"photoPublicId":{"type":"string","example":"teruf/volunteers/abc"},"photoFrame":{"$ref":"#/components/schemas/ImageFrameDto"},"isPublished":{"type":"boolean","example":true}}},"CreateDonationDto":{"type":"object","properties":{"donorName":{"type":"string","example":"Emeka Opara"},"donorEmail":{"type":"string","example":"emeka.opara@gmail.com"},"donorPhone":{"type":"string","example":"+2348012345678"},"amount":{"type":"number","example":150,"minimum":1},"currency":{"type":"string","example":"USD","default":"USD"},"frequency":{"type":"string","enum":["one-time","monthly","quarterly","annually"],"example":"one-time"},"designation":{"type":"string","example":"Subsidized Counseling Fund"},"paymentMethod":{"type":"string","example":"Card ending in 4242"},"transactionId":{"type":"string","example":"txn_123456789"},"paymentReference":{"type":"string","example":"teruf_don_1234567890"},"message":{"type":"string","example":"Thank you for your amazing work!"},"isAnonymous":{"type":"boolean","example":false}},"required":["donorName","donorEmail","amount"]},"InitializeDonationPaymentDto":{"type":"object","properties":{"donorName":{"type":"string","example":"Emeka Opara"},"donorEmail":{"type":"string","example":"emeka@gmail.com"},"amount":{"type":"number","example":5000,"description":"Amount in NGN (not kobo)"},"frequency":{"type":"string","enum":["one-time","monthly"],"default":"one-time"},"designation":{"type":"string","example":"General Operations Fund"}},"required":["donorName","donorEmail","amount"]},"UpdateDonationStatusDto":{"type":"object","properties":{"status":{"type":"string","enum":["pending","completed","failed","refunded"],"example":"completed"},"paymentReference":{"type":"string","example":"ref_123456"}},"required":["status"]},"CreateContactMessageDto":{"type":"object","properties":{"name":{"type":"string","example":"Pastor John Ademola"},"email":{"type":"string","example":"john.ademola@faithtabernacle.org"},"phone":{"type":"string","example":"+2348012345678"},"subject":{"type":"string","example":"Book Secondary School Workshop"},"message":{"type":"string","example":"Hello TERUF, we would like to invite Elizabeth and her team..."}},"required":["name","email","subject","message"]},"UpdateContactMessageStatusDto":{"type":"object","properties":{"status":{"type":"string","enum":["new","read","replied","resolved","archived"],"example":"resolved"},"replyMessage":{"type":"string","example":"Thank you for your inquiry. We will contact you shortly."}},"required":["status"]},"ReplyContactMessageDto":{"type":"object","properties":{"replyMessage":{"type":"string","example":"Thank you for reaching out. We can schedule you for Thursday."}},"required":["replyMessage"]},"SubscribeDto":{"type":"object","properties":{"email":{"type":"string","example":"flowcheq@gmail.com"},"name":{"type":"string","example":"John Doe"}},"required":["email"]},"UpdateSubscriberDto":{"type":"object","properties":{"name":{"type":"string","example":"John Doe"},"isActive":{"type":"boolean","example":true}}},"CreateBroadcastDto":{"type":"object","properties":{"subject":{"type":"string","example":"Welcome to the TERUF Community Newsletter"},"body":{"type":"string","example":"Dear partners, thank you for subscribing to our official updates list..."}},"required":["subject","body"]},"CreateResourcePurchaseDto":{"type":"object","properties":{"buyerName":{"type":"string","example":"Grace Kolawole"},"buyerEmail":{"type":"string","example":"grace.kolawole@gmail.com"},"buyerPhone":{"type":"string","example":"+2348012345678"},"paymentMethod":{"type":"string","example":"Card ending in 4242"},"paymentReference":{"type":"string","example":"txn_abc123"},"currency":{"type":"string","example":"USD"},"amount":{"type":"number","example":14.99}},"required":["buyerName","buyerEmail"]},"CreateProgramBookingDto":{"type":"object","properties":{"attendeeName":{"type":"string","example":"John Ademola"},"attendeeEmail":{"type":"string","example":"john.ademola@faithtabernacle.org"},"attendeePhone":{"type":"string","example":"+2348012345678"},"paymentMethod":{"type":"string","example":"Card ending in 4242"},"paymentReference":{"type":"string","example":"txn_booking_123"},"currency":{"type":"string","example":"USD"},"amount":{"type":"number","example":25}},"required":["attendeeName","attendeeEmail"]}}}}