diff --git a/API/ROLAC.API/Controllers/MembersController.cs b/API/ROLAC.API/Controllers/MembersController.cs
new file mode 100644
index 0000000..5288c32
--- /dev/null
+++ b/API/ROLAC.API/Controllers/MembersController.cs
@@ -0,0 +1,62 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using ROLAC.API.DTOs.Members;
+using ROLAC.API.Services;
+
+namespace ROLAC.API.Controllers;
+
+[ApiController]
+[Route("api/members")]
+[Authorize]
+public class MembersController : ControllerBase
+{
+ private readonly IMemberService _members;
+ public MembersController(IMemberService members) => _members = members;
+
+ /// GET /api/members?page=1&pageSize=20&search=Chen&status=Member&hasUser=false
+ [HttpGet]
+ [Authorize(Roles = "super_admin,secretary,pastor")]
+ public async Task GetPaged(
+ [FromQuery] int page = 1,
+ [FromQuery] int pageSize = 20,
+ [FromQuery] string? search = null,
+ [FromQuery] string? status = null,
+ [FromQuery] bool? hasUser = null)
+ => Ok(await _members.GetPagedAsync(page, pageSize, search, status, hasUser));
+
+ /// GET /api/members/{id}
+ [HttpGet("{id:int}")]
+ [Authorize(Roles = "super_admin,secretary,pastor")]
+ public async Task GetById(int id)
+ {
+ var dto = await _members.GetByIdAsync(id);
+ return dto is null ? NotFound() : Ok(dto);
+ }
+
+ /// POST /api/members
+ [HttpPost]
+ [Authorize(Roles = "super_admin,secretary")]
+ public async Task Create([FromBody] CreateMemberRequest request)
+ {
+ var id = await _members.CreateAsync(request);
+ return CreatedAtAction(nameof(GetById), new { id }, new { id });
+ }
+
+ /// PUT /api/members/{id}
+ [HttpPut("{id:int}")]
+ [Authorize(Roles = "super_admin,secretary")]
+ public async Task Update(int id, [FromBody] UpdateMemberRequest request)
+ {
+ try { await _members.UpdateAsync(id, request); return NoContent(); }
+ catch (KeyNotFoundException) { return NotFound(); }
+ }
+
+ /// DELETE /api/members/{id} — soft delete
+ [HttpDelete("{id:int}")]
+ [Authorize(Roles = "super_admin,secretary")]
+ public async Task Delete(int id)
+ {
+ try { await _members.DeleteAsync(id); return NoContent(); }
+ catch (KeyNotFoundException) { return NotFound(); }
+ }
+}
diff --git a/API/ROLAC.API/Program.cs b/API/ROLAC.API/Program.cs
index 019b708..3272ca5 100644
--- a/API/ROLAC.API/Program.cs
+++ b/API/ROLAC.API/Program.cs
@@ -82,8 +82,9 @@ builder.Services.AddCors(opt =>
// ---------------------------------------------------------------------------
// Application services
// ---------------------------------------------------------------------------
-builder.Services.AddScoped();
-builder.Services.AddScoped();
+builder.Services.AddScoped();
+builder.Services.AddScoped();
+builder.Services.AddScoped();
// ---------------------------------------------------------------------------
// Swagger / MVC