api-design

Expert API design agent for EasyPlatform following platform patterns and REST best practices.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "api-design" with this command: npx skills add duc01226/easyplatform/duc01226-easyplatform-api-design

REST API Design

Expert API design agent for EasyPlatform following platform patterns and REST best practices.

Controller Pattern

[ApiController] [Route("api/[controller]")] [PlatformAuthorize] // Require authentication public class EmployeeController : PlatformBaseController { // GET api/employee - List with filtering [HttpGet] public async Task<IActionResult> GetList([FromQuery] GetEmployeeListQuery query) => Ok(await Cqrs.SendAsync(query));

// GET api/employee/{id} - Single by ID
[HttpGet("{id}")]
public async Task&#x3C;IActionResult> GetById(string id)
    => Ok(await Cqrs.SendAsync(new GetEmployeeByIdQuery { Id = id }));

// POST api/employee - Create/Update
[HttpPost]
[PlatformAuthorize(Roles = "Admin,Manager")]
public async Task&#x3C;IActionResult> Save([FromBody] SaveEmployeeCommand command)
    => Ok(await Cqrs.SendAsync(command));

// DELETE api/employee/{id} - Delete
[HttpDelete("{id}")]
[PlatformAuthorize(Roles = "Admin")]
public async Task&#x3C;IActionResult> Delete(string id)
    => Ok(await Cqrs.SendAsync(new DeleteEmployeeCommand { Id = id }));

// POST api/employee/search - Complex search
[HttpPost("search")]
public async Task&#x3C;IActionResult> Search([FromBody] SearchEmployeesQuery query)
    => Ok(await Cqrs.SendAsync(query));

// POST api/employee/{id}/action - Custom action
[HttpPost("{id}/activate")]
public async Task&#x3C;IActionResult> Activate(string id)
    => Ok(await Cqrs.SendAsync(new ActivateEmployeeCommand { Id = id }));

}

Route Naming Conventions

Action HTTP Method Route Pattern Example

List GET /api/{resource}

GET /api/employees

Get by ID GET /api/{resource}/{id}

GET /api/employees/123

Create/Update POST /api/{resource}

POST /api/employees

Delete DELETE /api/{resource}/{id}

DELETE /api/employees/123

Complex Search POST /api/{resource}/search

POST /api/employees/search

Custom Action POST /api/{resource}/{id}/{action}

POST /api/employees/123/activate

Nested Resource GET /api/{parent}/{id}/{child}

GET /api/departments/1/employees

Request/Response DTOs

Query DTO (GET requests)

// Simple query params - use record public record GetEmployeeListQuery : PlatformCqrsPagedQuery<GetEmployeeListQueryResult, EmployeeDto> { public List<EmploymentStatus>? Statuses { get; init; } public string? SearchText { get; init; } public string? DepartmentId { get; init; } }

Command DTO (POST/PUT/DELETE)

public sealed class SaveEmployeeCommand : PlatformCqrsCommand<SaveEmployeeCommandResult> { public string? Id { get; set; } // Null for create public string FirstName { get; set; } = string.Empty; public string LastName { get; set; } = string.Empty; public string Email { get; set; } = string.Empty;

public override PlatformValidationResult&#x3C;IPlatformCqrsRequest> Validate()
{
    return base.Validate()
        .And(_ => FirstName.IsNotNullOrEmpty(), "FirstName is required")
        .And(_ => Email.IsNotNullOrEmpty(), "Email is required")
        .And(_ => Email.Contains("@"), "Invalid email format");
}

}

Response DTO

// For single entity public sealed class SaveEmployeeCommandResult : PlatformCqrsCommandResult { public EmployeeDto Entity { get; set; } = null!; }

// For paged list public sealed class GetEmployeeListQueryResult : PlatformCqrsPagedQueryResult<EmployeeDto> { public Dictionary<EmploymentStatus, int> StatusCounts { get; set; } = new();

public GetEmployeeListQueryResult(List&#x3C;Employee> items, int total, GetEmployeeListQuery req, Dictionary&#x3C;EmploymentStatus, int> counts)
    : base(items.SelectList(e => new EmployeeDto(e)), total, req)
{
    StatusCounts = counts;
}

}

Authorization Patterns

// Controller level - all endpoints [PlatformAuthorize] public class SecureController : PlatformBaseController { }

// Endpoint level - specific roles [HttpPost] [PlatformAuthorize(Roles = "Admin,Manager")] public async Task<IActionResult> AdminOnly() { }

// Handler level - business validation protected override async Task<PlatformValidationResult<T>> ValidateRequestAsync(...) { return await validation .And(_ => RequestContext.HasRole("Admin") || RequestContext.UserId() == req.TargetUserId, "Can only modify own data or be Admin"); }

File Upload Endpoints

[HttpPost("upload")] [RequestSizeLimit(50 * 1024 * 1024)] // 50MB public async Task<IActionResult> Upload([FromForm] UploadCommand command) => Ok(await Cqrs.SendAsync(command));

public sealed class UploadCommand : PlatformCqrsCommand<UploadCommandResult> { [FromForm] public IFormFile File { get; set; } = null!;

[FromForm]
public string? Description { get; set; }

}

Error Response Format

// Platform handles errors automatically with standard format { "type": "validation", "title": "Validation Error", "status": 400, "errors": { "email": ["Email is required", "Invalid email format"], "firstName": ["FirstName is required"] } }

// Business errors { "type": "business", "title": "Business Rule Violation", "status": 422, "detail": "Employee is already assigned to this department" }

API Design Checklist

  • RESTful route naming (plural nouns, lowercase)?

  • Appropriate HTTP methods?

  • Proper authorization attributes?

  • Validation in Command/Query Validate()?

  • Consistent response format?

  • Paging for list endpoints?

  • Error handling follows platform patterns?

Anti-Patterns

  • Verbs in URLs: Use /employees/123/activate not /activateEmployee

  • Missing Authorization: Always add [PlatformAuthorize]

  • Validation in Controller: Move to Command/Query Validate()

  • Business Logic in Controller: Keep controllers thin, logic in handlers

  • Inconsistent Naming: Follow {Resource}Controller pattern

Task Planning Notes

  • Always plan and break many small todo tasks

  • Always add a final review todo task to review the works done at the end to find any fix or enhancement needed

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Automation

workflow-refactor

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

workflow-full-feature-lifecycle

No summary provided by upstream source.

Repository SourceNeeds Review
Automation

workflow-deployment

No summary provided by upstream source.

Repository SourceNeeds Review